pidgr_proto/pidgr/v1/pidgr.v1.rs
1// @generated
2// This file is @generated by prost-build.
3// ─── Messages ───────────────────────────────────────────────────────────────
4
5/// Request to submit a user action on a delivered message.
6#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7pub struct SubmitActionRequest {
8 /// ID of the delivery the user is acting on.
9 /// Constraints: UUID format (36 characters).
10 #[prost(string, tag="1")]
11 pub delivery_id: ::prost::alloc::string::String,
12 /// ID of the action being performed (matches MessageAction.id).
13 /// Constraints: Max length 100 characters.
14 #[prost(string, tag="2")]
15 pub action_id: ::prost::alloc::string::String,
16 /// Optional action-specific payload (e.g. poll response data). Empty for ACK.
17 /// Constraints: Max size 10000 bytes.
18 #[prost(bytes="vec", tag="3")]
19 pub payload: ::prost::alloc::vec::Vec<u8>,
20}
21/// Response after submitting an action.
22#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
23pub struct SubmitActionResponse {
24 /// Whether the action was successfully recorded and forwarded to the workflow.
25 #[prost(bool, tag="1")]
26 pub success: bool,
27}
28// ─── Messages ───────────────────────────────────────────────────────────────
29
30/// A single channel dispatch event for the audit trail. Append-only; the
31/// receiver enforces idempotency on terminal states via a partial unique index
32/// on (campaign_id, recipient_user_id, channel, step_kind).
33#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
34pub struct ChannelEvent {
35 #[prost(string, tag="1")]
36 pub org_id: ::prost::alloc::string::String,
37 #[prost(string, tag="2")]
38 pub campaign_id: ::prost::alloc::string::String,
39 #[prost(string, tag="3")]
40 pub recipient_user_id: ::prost::alloc::string::String,
41 #[prost(enumeration="ChannelName", tag="4")]
42 pub channel: i32,
43 #[prost(enumeration="ChannelStepKind", tag="5")]
44 pub step_kind: i32,
45 #[prost(enumeration="ChannelEventStatus", tag="6")]
46 pub status: i32,
47 /// Set only when status = SKIPPED. UNSPECIFIED in all other cases.
48 #[prost(enumeration="ChannelSkipReason", tag="7")]
49 pub skip_reason: i32,
50 /// Provider's identifier for this dispatch. Empty for SKIPPED events.
51 #[prost(string, tag="8")]
52 pub provider_message_id: ::prost::alloc::string::String,
53 /// Cost in micros (1/1000000 of a USD). Zero for absorbed channels.
54 /// Negative is invalid.
55 #[prost(int64, tag="9")]
56 pub cost_micros: i64,
57 /// Free-form provider error payload on FAILED. JSON-encoded; opaque to
58 /// the platform.
59 #[prost(string, tag="10")]
60 pub metadata_json: ::prost::alloc::string::String,
61 #[prost(message, optional, tag="11")]
62 pub occurred_at: ::core::option::Option<::prost_types::Timestamp>,
63}
64#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
65pub struct RecordChannelEventRequest {
66 #[prost(message, optional, tag="1")]
67 pub event: ::core::option::Option<ChannelEvent>,
68}
69#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
70pub struct RecordChannelEventResponse {
71 /// True if the row was inserted. False if rejected as a duplicate of an
72 /// existing terminal-state row.
73 #[prost(bool, tag="1")]
74 pub accepted: bool,
75 /// "duplicate" when accepted=false and the partial unique index rejected
76 /// the insert. Empty when accepted=true.
77 #[prost(string, tag="2")]
78 pub reason: ::prost::alloc::string::String,
79}
80#[derive(Clone, PartialEq, ::prost::Message)]
81pub struct RecordChannelEventBatchRequest {
82 #[prost(message, repeated, tag="1")]
83 pub events: ::prost::alloc::vec::Vec<ChannelEvent>,
84}
85/// Per-event result inside a batch. Order matches the request's events list.
86#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
87pub struct RecordChannelEventBatchResult {
88 #[prost(bool, tag="1")]
89 pub accepted: bool,
90 #[prost(string, tag="2")]
91 pub reason: ::prost::alloc::string::String,
92}
93#[derive(Clone, PartialEq, ::prost::Message)]
94pub struct RecordChannelEventBatchResponse {
95 #[prost(message, repeated, tag="1")]
96 pub results: ::prost::alloc::vec::Vec<RecordChannelEventBatchResult>,
97}
98// ─── Enums ──────────────────────────────────────────────────────────────────
99
100/// Third-party notification channel for reminder + escalation dispatch.
101///
102/// Push is intentionally NOT in this enum. Push is the primary channel; it
103/// always fires alongside any third-party channels. The third-party channels
104/// here are additive. Channels carry only a deeplink notification — message
105/// content stays in the platform.
106#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
107#[repr(i32)]
108pub enum ChannelName {
109 Unspecified = 0,
110 Email = 1,
111 Webhook = 2,
112 Telegram = 3,
113 Slack = 4,
114 Sms = 5,
115 Whatsapp = 6,
116 MicrosoftTeams = 7,
117 Line = 8,
118 GoogleChat = 9,
119}
120impl ChannelName {
121 /// String value of the enum field names used in the ProtoBuf definition.
122 ///
123 /// The values are not transformed in any way and thus are considered stable
124 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
125 pub fn as_str_name(&self) -> &'static str {
126 match self {
127 Self::Unspecified => "CHANNEL_NAME_UNSPECIFIED",
128 Self::Email => "CHANNEL_NAME_EMAIL",
129 Self::Webhook => "CHANNEL_NAME_WEBHOOK",
130 Self::Telegram => "CHANNEL_NAME_TELEGRAM",
131 Self::Slack => "CHANNEL_NAME_SLACK",
132 Self::Sms => "CHANNEL_NAME_SMS",
133 Self::Whatsapp => "CHANNEL_NAME_WHATSAPP",
134 Self::MicrosoftTeams => "CHANNEL_NAME_MICROSOFT_TEAMS",
135 Self::Line => "CHANNEL_NAME_LINE",
136 Self::GoogleChat => "CHANNEL_NAME_GOOGLE_CHAT",
137 }
138 }
139 /// Creates an enum from field names used in the ProtoBuf definition.
140 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
141 match value {
142 "CHANNEL_NAME_UNSPECIFIED" => Some(Self::Unspecified),
143 "CHANNEL_NAME_EMAIL" => Some(Self::Email),
144 "CHANNEL_NAME_WEBHOOK" => Some(Self::Webhook),
145 "CHANNEL_NAME_TELEGRAM" => Some(Self::Telegram),
146 "CHANNEL_NAME_SLACK" => Some(Self::Slack),
147 "CHANNEL_NAME_SMS" => Some(Self::Sms),
148 "CHANNEL_NAME_WHATSAPP" => Some(Self::Whatsapp),
149 "CHANNEL_NAME_MICROSOFT_TEAMS" => Some(Self::MicrosoftTeams),
150 "CHANNEL_NAME_LINE" => Some(Self::Line),
151 "CHANNEL_NAME_GOOGLE_CHAT" => Some(Self::GoogleChat),
152 _ => None,
153 }
154 }
155}
156/// Workflow step kind that triggered the channel dispatch. Different step
157/// kinds for the same (campaign, recipient, channel) tuple are treated as
158/// distinct dispatch events for idempotency purposes.
159#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
160#[repr(i32)]
161pub enum ChannelStepKind {
162 Unspecified = 0,
163 Reminder = 1,
164 Escalation = 2,
165}
166impl ChannelStepKind {
167 /// String value of the enum field names used in the ProtoBuf definition.
168 ///
169 /// The values are not transformed in any way and thus are considered stable
170 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
171 pub fn as_str_name(&self) -> &'static str {
172 match self {
173 Self::Unspecified => "CHANNEL_STEP_KIND_UNSPECIFIED",
174 Self::Reminder => "CHANNEL_STEP_KIND_REMINDER",
175 Self::Escalation => "CHANNEL_STEP_KIND_ESCALATION",
176 }
177 }
178 /// Creates an enum from field names used in the ProtoBuf definition.
179 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
180 match value {
181 "CHANNEL_STEP_KIND_UNSPECIFIED" => Some(Self::Unspecified),
182 "CHANNEL_STEP_KIND_REMINDER" => Some(Self::Reminder),
183 "CHANNEL_STEP_KIND_ESCALATION" => Some(Self::Escalation),
184 _ => None,
185 }
186 }
187}
188/// Status of a channel dispatch attempt. The table is append-only — each state
189/// transition (e.g. SENT → DELIVERED via provider webhook) is its own row keyed
190/// off provider_message_id, not an UPDATE.
191#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
192#[repr(i32)]
193pub enum ChannelEventStatus {
194 Unspecified = 0,
195 Sent = 1,
196 Delivered = 2,
197 Opened = 3,
198 Clicked = 4,
199 Bounced = 5,
200 Failed = 6,
201 Skipped = 7,
202}
203impl ChannelEventStatus {
204 /// String value of the enum field names used in the ProtoBuf definition.
205 ///
206 /// The values are not transformed in any way and thus are considered stable
207 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
208 pub fn as_str_name(&self) -> &'static str {
209 match self {
210 Self::Unspecified => "CHANNEL_EVENT_STATUS_UNSPECIFIED",
211 Self::Sent => "CHANNEL_EVENT_STATUS_SENT",
212 Self::Delivered => "CHANNEL_EVENT_STATUS_DELIVERED",
213 Self::Opened => "CHANNEL_EVENT_STATUS_OPENED",
214 Self::Clicked => "CHANNEL_EVENT_STATUS_CLICKED",
215 Self::Bounced => "CHANNEL_EVENT_STATUS_BOUNCED",
216 Self::Failed => "CHANNEL_EVENT_STATUS_FAILED",
217 Self::Skipped => "CHANNEL_EVENT_STATUS_SKIPPED",
218 }
219 }
220 /// Creates an enum from field names used in the ProtoBuf definition.
221 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
222 match value {
223 "CHANNEL_EVENT_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
224 "CHANNEL_EVENT_STATUS_SENT" => Some(Self::Sent),
225 "CHANNEL_EVENT_STATUS_DELIVERED" => Some(Self::Delivered),
226 "CHANNEL_EVENT_STATUS_OPENED" => Some(Self::Opened),
227 "CHANNEL_EVENT_STATUS_CLICKED" => Some(Self::Clicked),
228 "CHANNEL_EVENT_STATUS_BOUNCED" => Some(Self::Bounced),
229 "CHANNEL_EVENT_STATUS_FAILED" => Some(Self::Failed),
230 "CHANNEL_EVENT_STATUS_SKIPPED" => Some(Self::Skipped),
231 _ => None,
232 }
233 }
234}
235/// Reason a dispatch was SKIPPED rather than attempted. Set when status is
236/// CHANNEL_EVENT_STATUS_SKIPPED; UNSPECIFIED otherwise.
237#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
238#[repr(i32)]
239pub enum ChannelSkipReason {
240 Unspecified = 0,
241 OptedOut = 1,
242 RegionBlocked = 2,
243 CostCapExceeded = 3,
244 NoIdentifier = 4,
245}
246impl ChannelSkipReason {
247 /// String value of the enum field names used in the ProtoBuf definition.
248 ///
249 /// The values are not transformed in any way and thus are considered stable
250 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
251 pub fn as_str_name(&self) -> &'static str {
252 match self {
253 Self::Unspecified => "CHANNEL_SKIP_REASON_UNSPECIFIED",
254 Self::OptedOut => "CHANNEL_SKIP_REASON_OPTED_OUT",
255 Self::RegionBlocked => "CHANNEL_SKIP_REASON_REGION_BLOCKED",
256 Self::CostCapExceeded => "CHANNEL_SKIP_REASON_COST_CAP_EXCEEDED",
257 Self::NoIdentifier => "CHANNEL_SKIP_REASON_NO_IDENTIFIER",
258 }
259 }
260 /// Creates an enum from field names used in the ProtoBuf definition.
261 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
262 match value {
263 "CHANNEL_SKIP_REASON_UNSPECIFIED" => Some(Self::Unspecified),
264 "CHANNEL_SKIP_REASON_OPTED_OUT" => Some(Self::OptedOut),
265 "CHANNEL_SKIP_REASON_REGION_BLOCKED" => Some(Self::RegionBlocked),
266 "CHANNEL_SKIP_REASON_COST_CAP_EXCEEDED" => Some(Self::CostCapExceeded),
267 "CHANNEL_SKIP_REASON_NO_IDENTIFIER" => Some(Self::NoIdentifier),
268 _ => None,
269 }
270 }
271}
272/// A named role within an organization with a set of permissions.
273#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
274pub struct Role {
275 /// Unique identifier for the role.
276 #[prost(string, tag="1")]
277 pub id: ::prost::alloc::string::String,
278 /// URL-safe slug (unique within the organization, e.g. "admin", "manager").
279 #[prost(string, tag="2")]
280 pub slug: ::prost::alloc::string::String,
281 /// Human-readable display name.
282 #[prost(string, tag="3")]
283 pub name: ::prost::alloc::string::String,
284 /// Whether this role was seeded by the system on organization creation.
285 #[prost(bool, tag="4")]
286 pub is_default: bool,
287 /// Permissions granted to users with this role.
288 #[prost(enumeration="Permission", repeated, tag="5")]
289 pub permissions: ::prost::alloc::vec::Vec<i32>,
290 /// Whether this role is system-managed and immutable (e.g. super_admin).
291 #[prost(bool, tag="6")]
292 pub is_system: bool,
293}
294// ─── Pagination ─────────────────────────────────────────────────────────────
295
296/// Cursor-based pagination parameters for list requests.
297#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
298pub struct Pagination {
299 /// Maximum number of items to return per page.
300 #[prost(int32, tag="1")]
301 pub page_size: i32,
302 /// Opaque token from a previous response to fetch the next page.
303 #[prost(string, tag="2")]
304 pub page_token: ::prost::alloc::string::String,
305}
306/// Pagination metadata returned alongside list responses.
307#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
308pub struct PaginationMeta {
309 /// Token to pass in the next request to get the following page. Empty if no more pages.
310 #[prost(string, tag="1")]
311 pub next_page_token: ::prost::alloc::string::String,
312 /// Total number of items matching the query (across all pages).
313 #[prost(int32, tag="2")]
314 pub total_count: i32,
315}
316// ─── Message & Action Model ─────────────────────────────────────────────────
317
318/// An action button attached to a message that a recipient can interact with.
319#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
320pub struct MessageAction {
321 /// Unique identifier for this action within the message.
322 #[prost(string, tag="1")]
323 pub id: ::prost::alloc::string::String,
324 /// The type of action (e.g. ACK).
325 #[prost(enumeration="ActionType", tag="2")]
326 pub r#type: i32,
327 /// Display label shown to the recipient (e.g. "Got it").
328 /// Constraints: Max length 50 characters.
329 #[prost(string, tag="3")]
330 pub label: ::prost::alloc::string::String,
331}
332/// Canonical message type used across rendering, inbox, and delivery.
333/// Represents the fully rendered content delivered to a recipient.
334#[derive(Clone, PartialEq, ::prost::Message)]
335pub struct Message {
336 /// SHA-256 hash of the rendered content, used as a content-addressable ID.
337 #[prost(string, tag="1")]
338 pub content_id: ::prost::alloc::string::String,
339 /// ID of the campaign this message belongs to.
340 #[prost(string, tag="2")]
341 pub campaign_id: ::prost::alloc::string::String,
342 /// Display name of the sender (e.g. organization or campaign name).
343 /// Constraints: Max length 200 characters.
344 #[prost(string, tag="3")]
345 pub sender_name: ::prost::alloc::string::String,
346 /// Short one-line summary shown in notification banners.
347 /// Constraints: Max length 500 characters.
348 #[prost(string, tag="4")]
349 pub summary: ::prost::alloc::string::String,
350 /// Preview text shown in inbox list views.
351 /// Constraints: Max length 500 characters.
352 #[prost(string, tag="5")]
353 pub preview: ::prost::alloc::string::String,
354 /// Full message body content.
355 /// Constraints: Max length 100000 characters.
356 #[prost(string, tag="6")]
357 pub body: ::prost::alloc::string::String,
358 /// Whether this message requires immediate attention from the recipient.
359 #[prost(bool, tag="7")]
360 pub critical: bool,
361 /// Actions available to the recipient (e.g. acknowledge button).
362 #[prost(message, repeated, tag="8")]
363 pub actions: ::prost::alloc::vec::Vec<MessageAction>,
364 /// Timestamp when the message was created.
365 #[prost(message, optional, tag="9")]
366 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
367 /// User-facing title of the message (resolved from campaign or template).
368 /// Constraints: Max length 200 characters.
369 #[prost(string, tag="10")]
370 pub title: ::prost::alloc::string::String,
371}
372// ─── Workflow Definition Model ──────────────────────────────────────────────
373
374/// A data-driven workflow represented as a directed acyclic graph (DAG) of steps.
375/// Defines the automation logic for a campaign's lifecycle.
376/// Backend MUST validate the graph is a DAG (no cycles) before execution.
377#[derive(Clone, PartialEq, ::prost::Message)]
378pub struct WorkflowDefinition {
379 /// Ordered list of steps in the workflow DAG.
380 /// Constraints: Max 100 steps. Backend MUST validate the graph is a DAG (no cycles).
381 #[prost(message, repeated, tag="1")]
382 pub steps: ::prost::alloc::vec::Vec<WorkflowStep>,
383}
384/// A single step in a workflow DAG with typed configuration and transitions.
385#[derive(Clone, PartialEq, ::prost::Message)]
386pub struct WorkflowStep {
387 /// Unique identifier for this step within the workflow.
388 #[prost(string, tag="1")]
389 pub id: ::prost::alloc::string::String,
390 /// The type of operation this step performs.
391 #[prost(enumeration="StepType", tag="2")]
392 pub r#type: i32,
393 /// Map of outcome labels to the next step ID (e.g. "completed" -> "step_3").
394 /// Constraints: Max 10 transitions per step.
395 #[prost(map="string, string", tag="7")]
396 pub transitions: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
397 /// Step-specific configuration — exactly one must be set, matching the type.
398 #[prost(oneof="workflow_step::Config", tags="3, 4, 5, 6, 8")]
399 pub config: ::core::option::Option<workflow_step::Config>,
400}
401/// Nested message and enum types in `WorkflowStep`.
402pub mod workflow_step {
403 /// Step-specific configuration — exactly one must be set, matching the type.
404 #[derive(Clone, PartialEq, ::prost::Oneof)]
405 pub enum Config {
406 /// Configuration for SEND_NOTIFICATION steps.
407 #[prost(message, tag="3")]
408 SendNotification(super::SendNotificationConfig),
409 /// Configuration for DEADLINE_CHECK steps.
410 #[prost(message, tag="4")]
411 DeadlineCheck(super::DeadlineCheckConfig),
412 /// Configuration for SEND_REMINDER steps.
413 #[prost(message, tag="5")]
414 SendReminder(super::SendReminderConfig),
415 /// Configuration for CALL_WEBHOOK steps.
416 #[prost(message, tag="6")]
417 CallWebhook(super::CallWebhookConfig),
418 /// Configuration for STEP_TYPE_ESCALATE steps.
419 #[prost(message, tag="8")]
420 EscalateConfig(super::EscalateConfig),
421 }
422}
423/// Configuration for a step that sends the initial push notification.
424#[derive(Clone, PartialEq, ::prost::Message)]
425pub struct SendNotificationConfig {
426 /// Notification delivery type (e.g. "push").
427 /// Constraints: Accepted values: "push". Max length 50 characters.
428 #[prost(string, tag="1")]
429 pub r#type: ::prost::alloc::string::String,
430 /// ID of the template to use for this step's notification.
431 /// Empty falls back to campaign-level template_id.
432 /// Constraints: Max length 36 characters (UUID).
433 #[prost(string, tag="2")]
434 pub template_id: ::prost::alloc::string::String,
435 /// Pinned template version for this step.
436 /// 0 falls back to campaign-level template_version.
437 #[prost(int32, tag="3")]
438 pub template_version: i32,
439 /// Display label for the action button (e.g. "Acknowledge", "Got it").
440 /// Constraints: Max length 50 characters.
441 #[prost(string, tag="4")]
442 pub action_label: ::prost::alloc::string::String,
443 /// Action type for this step's message button.
444 #[prost(enumeration="ActionType", tag="5")]
445 pub action_type: i32,
446 /// Values for custom-sourced template variables specific to this step.
447 /// Constraints: Max 100 entries. Key max length 100 characters, value max length 10000 characters.
448 #[prost(map="string, string", tag="6")]
449 pub custom_variables: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
450}
451/// Configuration for a deadline-based timer step that sleeps for a configured
452/// delay before proceeding. Acknowledgments happen independently at the delivery
453/// level and are evaluated by subsequent steps (e.g. SEND_REMINDER).
454#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
455pub struct DeadlineCheckConfig {
456 /// Duration string for the deadline delay (e.g. "120h", "72h").
457 /// Constraints: Valid range 1m to 8760h (1 year).
458 #[prost(string, tag="1")]
459 pub delay: ::prost::alloc::string::String,
460}
461/// Configuration for a step that sends a one-time reminder to non-responsive recipients.
462#[derive(Clone, PartialEq, ::prost::Message)]
463pub struct SendReminderConfig {
464 /// Reminder delivery type (e.g. "push").
465 /// Constraints: Accepted values: "push". Max length 50 characters.
466 #[prost(string, tag="1")]
467 pub r#type: ::prost::alloc::string::String,
468 /// Additional third-party channels to dispatch the reminder through
469 /// alongside the primary push notification. Empty = push-only behaviour
470 /// (the platform's historical default; no surprise for existing
471 /// workflows). Each entry produces an independent dispatch attempt
472 /// recorded in `channel_events`; per-org configuration in
473 /// pidgr-integrations decides which channels are eligible at runtime.
474 #[prost(enumeration="ChannelName", repeated, tag="4")]
475 pub third_party_channels: ::prost::alloc::vec::Vec<i32>,
476 /// Third parties to loop in when this reminder fires. Each resolved
477 /// target receives a passive inbox delivery (no action button) plus a
478 /// fan-out via the same `third_party_channels` list as the employee
479 /// reminder. The delivery auto-dismisses when the original recipient
480 /// acknowledges the campaign.
481 ///
482 /// Each entry reuses the existing `EscalationTarget` shape
483 /// (USER / GROUP / MANAGER / ROLE). When `type` is MANAGER, `target_id`
484 /// is empty and is resolved at runtime from the original recipient's
485 /// `manager_id`. Self-targets (resolved user_id == original recipient)
486 /// are dropped at dispatch time.
487 /// Constraints: Max 5 entries.
488 #[prost(message, repeated, tag="5")]
489 pub notify_targets: ::prost::alloc::vec::Vec<EscalationTarget>,
490}
491/// Configuration for a step that calls an external webhook.
492#[derive(Clone, PartialEq, ::prost::Message)]
493pub struct CallWebhookConfig {
494 /// Human-readable name for this webhook (for logging/display).
495 /// Constraints: Max length 200 characters.
496 #[prost(string, tag="1")]
497 pub name: ::prost::alloc::string::String,
498 /// URL to POST campaign context to.
499 /// Constraints: Max length 2048 characters.
500 /// Security: HTTPS required in production. Backend MUST reject private,
501 /// loopback, and link-local addresses to prevent SSRF attacks.
502 #[prost(string, tag="2")]
503 pub url: ::prost::alloc::string::String,
504 /// Additional HTTP headers to include in the webhook request.
505 /// Constraints: Max 20 entries. Key max length 200 characters, value max length 2000 characters.
506 #[prost(map="string, string", tag="3")]
507 pub headers: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
508}
509/// A target for escalation — who should be notified when escalation fires.
510#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
511pub struct EscalationTarget {
512 /// Type of target.
513 #[prost(enumeration="EscalationTargetType", tag="1")]
514 pub r#type: i32,
515 /// ID of the target (user_id, group_id, or role_id).
516 /// Empty for MANAGER type (resolved at runtime from recipient's manager_id).
517 #[prost(string, tag="2")]
518 pub target_id: ::prost::alloc::string::String,
519}
520/// Configuration for an escalation step in the workflow DAG.
521#[derive(Clone, PartialEq, ::prost::Message)]
522pub struct EscalateConfig {
523 /// Condition that triggers escalation.
524 #[prost(enumeration="EscalationCondition", tag="1")]
525 pub condition: i32,
526 /// Targets to notify when escalation fires.
527 #[prost(message, repeated, tag="2")]
528 pub targets: ::prost::alloc::vec::Vec<EscalationTarget>,
529 /// Number of times to repeat this escalation before moving to the next step.
530 /// Constraints: Max 5.
531 #[prost(int32, tag="3")]
532 pub repeat_count: i32,
533 /// Minutes between repeat attempts.
534 #[prost(int32, tag="4")]
535 pub repeat_interval_minutes: i32,
536 /// Behavior mode for this escalation. UNSPECIFIED is normalized to DELIVER.
537 #[prost(enumeration="EscalateMode", tag="5")]
538 pub mode: i32,
539 /// Additional third-party channels to dispatch the escalation through
540 /// alongside the primary push / delivery side effect. Empty = no
541 /// third-party fan-out (existing behaviour). Each entry produces an
542 /// independent dispatch attempt recorded in `channel_events`. ALERT_ONLY
543 /// and DELIVER modes both support third-party fan-out — the channel
544 /// adapters render the alert content from the campaign + a
545 /// mode-aware copy variant.
546 #[prost(enumeration="ChannelName", repeated, tag="6")]
547 pub third_party_channels: ::prost::alloc::vec::Vec<i32>,
548}
549// ─── Status Enums ───────────────────────────────────────────────────────────
550
551/// Lifecycle status of a campaign.
552#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
553#[repr(i32)]
554pub enum CampaignStatus {
555 /// Default value; not a valid status.
556 Unspecified = 0,
557 /// Campaign has been created but not yet started.
558 Created = 1,
559 /// Campaign is actively delivering messages and processing actions.
560 Running = 2,
561 /// All recipients have been processed; campaign is finished.
562 Completed = 3,
563 /// Campaign terminated due to an unrecoverable error.
564 Failed = 4,
565 /// Campaign was manually cancelled before completion.
566 Cancelled = 5,
567}
568impl CampaignStatus {
569 /// String value of the enum field names used in the ProtoBuf definition.
570 ///
571 /// The values are not transformed in any way and thus are considered stable
572 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
573 pub fn as_str_name(&self) -> &'static str {
574 match self {
575 Self::Unspecified => "CAMPAIGN_STATUS_UNSPECIFIED",
576 Self::Created => "CAMPAIGN_STATUS_CREATED",
577 Self::Running => "CAMPAIGN_STATUS_RUNNING",
578 Self::Completed => "CAMPAIGN_STATUS_COMPLETED",
579 Self::Failed => "CAMPAIGN_STATUS_FAILED",
580 Self::Cancelled => "CAMPAIGN_STATUS_CANCELLED",
581 }
582 }
583 /// Creates an enum from field names used in the ProtoBuf definition.
584 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
585 match value {
586 "CAMPAIGN_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
587 "CAMPAIGN_STATUS_CREATED" => Some(Self::Created),
588 "CAMPAIGN_STATUS_RUNNING" => Some(Self::Running),
589 "CAMPAIGN_STATUS_COMPLETED" => Some(Self::Completed),
590 "CAMPAIGN_STATUS_FAILED" => Some(Self::Failed),
591 "CAMPAIGN_STATUS_CANCELLED" => Some(Self::Cancelled),
592 _ => None,
593 }
594 }
595}
596/// Delivery status for a single message sent to a recipient.
597#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
598#[repr(i32)]
599pub enum DeliveryStatus {
600 /// Default value; not a valid status.
601 Unspecified = 0,
602 /// Message is queued but has not been sent yet.
603 Pending = 1,
604 /// Push notification was sent to the delivery provider.
605 Sent = 2,
606 /// Message was confirmed delivered to the device.
607 Delivered = 3,
608 /// Recipient completed the required action (e.g. acknowledged).
609 Acknowledged = 4,
610 /// Recipient did not act before the deadline.
611 Missed = 5,
612 /// Recipient has no registered device; delivery was skipped.
613 NoDevice = 6,
614 /// Delivery failed due to a provider or system error.
615 Failed = 7,
616}
617impl DeliveryStatus {
618 /// String value of the enum field names used in the ProtoBuf definition.
619 ///
620 /// The values are not transformed in any way and thus are considered stable
621 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
622 pub fn as_str_name(&self) -> &'static str {
623 match self {
624 Self::Unspecified => "DELIVERY_STATUS_UNSPECIFIED",
625 Self::Pending => "DELIVERY_STATUS_PENDING",
626 Self::Sent => "DELIVERY_STATUS_SENT",
627 Self::Delivered => "DELIVERY_STATUS_DELIVERED",
628 Self::Acknowledged => "DELIVERY_STATUS_ACKNOWLEDGED",
629 Self::Missed => "DELIVERY_STATUS_MISSED",
630 Self::NoDevice => "DELIVERY_STATUS_NO_DEVICE",
631 Self::Failed => "DELIVERY_STATUS_FAILED",
632 }
633 }
634 /// Creates an enum from field names used in the ProtoBuf definition.
635 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
636 match value {
637 "DELIVERY_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
638 "DELIVERY_STATUS_PENDING" => Some(Self::Pending),
639 "DELIVERY_STATUS_SENT" => Some(Self::Sent),
640 "DELIVERY_STATUS_DELIVERED" => Some(Self::Delivered),
641 "DELIVERY_STATUS_ACKNOWLEDGED" => Some(Self::Acknowledged),
642 "DELIVERY_STATUS_MISSED" => Some(Self::Missed),
643 "DELIVERY_STATUS_NO_DEVICE" => Some(Self::NoDevice),
644 "DELIVERY_STATUS_FAILED" => Some(Self::Failed),
645 _ => None,
646 }
647 }
648}
649/// Mobile platform for device registration.
650#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
651#[repr(i32)]
652pub enum Platform {
653 /// Default value; not a valid platform.
654 Unspecified = 0,
655 /// Apple iOS.
656 Ios = 1,
657 /// Google Android.
658 Android = 2,
659}
660impl Platform {
661 /// String value of the enum field names used in the ProtoBuf definition.
662 ///
663 /// The values are not transformed in any way and thus are considered stable
664 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
665 pub fn as_str_name(&self) -> &'static str {
666 match self {
667 Self::Unspecified => "PLATFORM_UNSPECIFIED",
668 Self::Ios => "PLATFORM_IOS",
669 Self::Android => "PLATFORM_ANDROID",
670 }
671 }
672 /// Creates an enum from field names used in the ProtoBuf definition.
673 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
674 match value {
675 "PLATFORM_UNSPECIFIED" => Some(Self::Unspecified),
676 "PLATFORM_IOS" => Some(Self::Ios),
677 "PLATFORM_ANDROID" => Some(Self::Android),
678 _ => None,
679 }
680 }
681}
682/// Granular permission for authorization checks.
683/// Stored in the database as enum names (e.g. "PERMISSION_ORG_READ").
684/// New values MUST be appended with the next sequential number; existing values
685/// MUST NOT be renumbered or removed (enforced by buf breaking).
686#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
687#[repr(i32)]
688pub enum Permission {
689 /// Default value; not a valid permission.
690 Unspecified = 0,
691 /// View organization settings.
692 OrgRead = 1,
693 /// Modify organization settings.
694 OrgWrite = 2,
695 /// View organization members.
696 MembersRead = 3,
697 /// Invite new users to the organization.
698 MembersInvite = 4,
699 /// Change user roles, deactivate users.
700 MembersManage = 5,
701 /// View campaigns and deliveries.
702 CampaignsRead = 6,
703 /// Create and edit campaigns.
704 CampaignsWrite = 7,
705 /// Start campaign execution.
706 CampaignsStart = 8,
707 /// View templates.
708 TemplatesRead = 9,
709 /// Create and edit templates.
710 TemplatesWrite = 10,
711 /// View inbox messages and deliveries.
712 InboxRead = 11,
713 /// Submit actions on deliveries.
714 InboxAct = 12,
715 /// View all groups in the organization.
716 GroupsAllRead = 13,
717 /// Create, edit, delete groups the caller created, manage own group membership.
718 GroupsWrite = 14,
719 /// Create, edit, delete any group in the organization, manage any group membership.
720 GroupsAllWrite = 15,
721 /// View all teams (organizational units) in the organization.
722 TeamsAllRead = 16,
723 /// Create, edit, delete teams the caller created, manage own team membership.
724 TeamsWrite = 17,
725 /// Create, edit, delete any team in the organization, manage any team membership.
726 TeamsAllWrite = 18,
727 /// View privacy requests (exports, deletions) for the organization.
728 PrivacyRead = 19,
729 /// Schedule deletions, export user data, restrict processing.
730 PrivacyWrite = 20,
731 /// View audit trail events for the organization.
732 AuditRead = 21,
733 /// Review and approve template translations.
734 TemplatesReview = 22,
735 /// Cross-organization read access for platform-level support operations.
736 /// Assignable only to roles within an ORG_TYPE_STAFF organization.
737 PlatformSupport = 23,
738 /// Manage platform access codes (generation, listing, revocation).
739 /// Assignable only to roles within an ORG_TYPE_STAFF organization.
740 PlatformAccessCodes = 24,
741 /// Provision and manage organizations at the platform level.
742 /// Assignable only to roles within an ORG_TYPE_STAFF organization.
743 PlatformProvision = 25,
744 /// Take abuse-response actions against organizations (suspend, revoke, quota overrides).
745 /// Assignable only to roles within an ORG_TYPE_STAFF organization.
746 PlatformAbuseResponse = 26,
747 /// Write subprocessor and compliance records at the platform level.
748 /// Assignable only to roles within an ORG_TYPE_STAFF organization.
749 PlatformComplianceWrite = 27,
750 /// Create synthetic (flagged) data on any org: seed resources and simulate
751 /// campaign outcomes. Assignable only to roles within an ORG_TYPE_STAFF organization.
752 PlatformSynthetic = 28,
753 /// Dispatch notifications to third-party channels (Slack, Telegram, webhook, etc.).
754 ChannelsDispatch = 29,
755 /// Create, update, or remove a member's third-party channel reachability.
756 ReachabilityWrite = 30,
757 /// Triage security incidents (list, classify, mark-notified) at the platform level.
758 /// Assignable only to roles within an ORG_TYPE_STAFF organization.
759 PlatformIncidents = 31,
760}
761impl Permission {
762 /// String value of the enum field names used in the ProtoBuf definition.
763 ///
764 /// The values are not transformed in any way and thus are considered stable
765 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
766 pub fn as_str_name(&self) -> &'static str {
767 match self {
768 Self::Unspecified => "PERMISSION_UNSPECIFIED",
769 Self::OrgRead => "PERMISSION_ORG_READ",
770 Self::OrgWrite => "PERMISSION_ORG_WRITE",
771 Self::MembersRead => "PERMISSION_MEMBERS_READ",
772 Self::MembersInvite => "PERMISSION_MEMBERS_INVITE",
773 Self::MembersManage => "PERMISSION_MEMBERS_MANAGE",
774 Self::CampaignsRead => "PERMISSION_CAMPAIGNS_READ",
775 Self::CampaignsWrite => "PERMISSION_CAMPAIGNS_WRITE",
776 Self::CampaignsStart => "PERMISSION_CAMPAIGNS_START",
777 Self::TemplatesRead => "PERMISSION_TEMPLATES_READ",
778 Self::TemplatesWrite => "PERMISSION_TEMPLATES_WRITE",
779 Self::InboxRead => "PERMISSION_INBOX_READ",
780 Self::InboxAct => "PERMISSION_INBOX_ACT",
781 Self::GroupsAllRead => "PERMISSION_GROUPS_ALL_READ",
782 Self::GroupsWrite => "PERMISSION_GROUPS_WRITE",
783 Self::GroupsAllWrite => "PERMISSION_GROUPS_ALL_WRITE",
784 Self::TeamsAllRead => "PERMISSION_TEAMS_ALL_READ",
785 Self::TeamsWrite => "PERMISSION_TEAMS_WRITE",
786 Self::TeamsAllWrite => "PERMISSION_TEAMS_ALL_WRITE",
787 Self::PrivacyRead => "PERMISSION_PRIVACY_READ",
788 Self::PrivacyWrite => "PERMISSION_PRIVACY_WRITE",
789 Self::AuditRead => "PERMISSION_AUDIT_READ",
790 Self::TemplatesReview => "PERMISSION_TEMPLATES_REVIEW",
791 Self::PlatformSupport => "PERMISSION_PLATFORM_SUPPORT",
792 Self::PlatformAccessCodes => "PERMISSION_PLATFORM_ACCESS_CODES",
793 Self::PlatformProvision => "PERMISSION_PLATFORM_PROVISION",
794 Self::PlatformAbuseResponse => "PERMISSION_PLATFORM_ABUSE_RESPONSE",
795 Self::PlatformComplianceWrite => "PERMISSION_PLATFORM_COMPLIANCE_WRITE",
796 Self::PlatformSynthetic => "PERMISSION_PLATFORM_SYNTHETIC",
797 Self::ChannelsDispatch => "PERMISSION_CHANNELS_DISPATCH",
798 Self::ReachabilityWrite => "PERMISSION_REACHABILITY_WRITE",
799 Self::PlatformIncidents => "PERMISSION_PLATFORM_INCIDENTS",
800 }
801 }
802 /// Creates an enum from field names used in the ProtoBuf definition.
803 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
804 match value {
805 "PERMISSION_UNSPECIFIED" => Some(Self::Unspecified),
806 "PERMISSION_ORG_READ" => Some(Self::OrgRead),
807 "PERMISSION_ORG_WRITE" => Some(Self::OrgWrite),
808 "PERMISSION_MEMBERS_READ" => Some(Self::MembersRead),
809 "PERMISSION_MEMBERS_INVITE" => Some(Self::MembersInvite),
810 "PERMISSION_MEMBERS_MANAGE" => Some(Self::MembersManage),
811 "PERMISSION_CAMPAIGNS_READ" => Some(Self::CampaignsRead),
812 "PERMISSION_CAMPAIGNS_WRITE" => Some(Self::CampaignsWrite),
813 "PERMISSION_CAMPAIGNS_START" => Some(Self::CampaignsStart),
814 "PERMISSION_TEMPLATES_READ" => Some(Self::TemplatesRead),
815 "PERMISSION_TEMPLATES_WRITE" => Some(Self::TemplatesWrite),
816 "PERMISSION_INBOX_READ" => Some(Self::InboxRead),
817 "PERMISSION_INBOX_ACT" => Some(Self::InboxAct),
818 "PERMISSION_GROUPS_ALL_READ" => Some(Self::GroupsAllRead),
819 "PERMISSION_GROUPS_WRITE" => Some(Self::GroupsWrite),
820 "PERMISSION_GROUPS_ALL_WRITE" => Some(Self::GroupsAllWrite),
821 "PERMISSION_TEAMS_ALL_READ" => Some(Self::TeamsAllRead),
822 "PERMISSION_TEAMS_WRITE" => Some(Self::TeamsWrite),
823 "PERMISSION_TEAMS_ALL_WRITE" => Some(Self::TeamsAllWrite),
824 "PERMISSION_PRIVACY_READ" => Some(Self::PrivacyRead),
825 "PERMISSION_PRIVACY_WRITE" => Some(Self::PrivacyWrite),
826 "PERMISSION_AUDIT_READ" => Some(Self::AuditRead),
827 "PERMISSION_TEMPLATES_REVIEW" => Some(Self::TemplatesReview),
828 "PERMISSION_PLATFORM_SUPPORT" => Some(Self::PlatformSupport),
829 "PERMISSION_PLATFORM_ACCESS_CODES" => Some(Self::PlatformAccessCodes),
830 "PERMISSION_PLATFORM_PROVISION" => Some(Self::PlatformProvision),
831 "PERMISSION_PLATFORM_ABUSE_RESPONSE" => Some(Self::PlatformAbuseResponse),
832 "PERMISSION_PLATFORM_COMPLIANCE_WRITE" => Some(Self::PlatformComplianceWrite),
833 "PERMISSION_PLATFORM_SYNTHETIC" => Some(Self::PlatformSynthetic),
834 "PERMISSION_CHANNELS_DISPATCH" => Some(Self::ChannelsDispatch),
835 "PERMISSION_REACHABILITY_WRITE" => Some(Self::ReachabilityWrite),
836 "PERMISSION_PLATFORM_INCIDENTS" => Some(Self::PlatformIncidents),
837 _ => None,
838 }
839 }
840}
841/// Type of action a recipient can perform on a message.
842#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
843#[repr(i32)]
844pub enum ActionType {
845 /// Default value; not a valid action type.
846 Unspecified = 0,
847 /// Simple acknowledgment — recipient confirms they received the message.
848 Ack = 1,
849}
850impl ActionType {
851 /// String value of the enum field names used in the ProtoBuf definition.
852 ///
853 /// The values are not transformed in any way and thus are considered stable
854 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
855 pub fn as_str_name(&self) -> &'static str {
856 match self {
857 Self::Unspecified => "ACTION_TYPE_UNSPECIFIED",
858 Self::Ack => "ACTION_TYPE_ACK",
859 }
860 }
861 /// Creates an enum from field names used in the ProtoBuf definition.
862 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
863 match value {
864 "ACTION_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
865 "ACTION_TYPE_ACK" => Some(Self::Ack),
866 _ => None,
867 }
868 }
869}
870/// Type of step within a workflow definition DAG.
871#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
872#[repr(i32)]
873pub enum StepType {
874 /// Default value; not a valid step type.
875 Unspecified = 0,
876 /// Send the initial push notification to all recipients.
877 SendNotification = 1,
878 /// Sleep for a configurable deadline, then proceed to the next step.
879 DeadlineCheck = 2,
880 /// Send a follow-up reminder to recipients who have not acted.
881 SendReminder = 3,
882 /// Call an external webhook with campaign context.
883 CallWebhook = 4,
884 /// Mark unacknowledged deliveries (SENT/DELIVERED) as MISSED. No config required.
885 MarkMissed = 5,
886 /// Escalate unacknowledged deliveries to configured targets.
887 Escalate = 6,
888}
889impl StepType {
890 /// String value of the enum field names used in the ProtoBuf definition.
891 ///
892 /// The values are not transformed in any way and thus are considered stable
893 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
894 pub fn as_str_name(&self) -> &'static str {
895 match self {
896 Self::Unspecified => "STEP_TYPE_UNSPECIFIED",
897 Self::SendNotification => "STEP_TYPE_SEND_NOTIFICATION",
898 Self::DeadlineCheck => "STEP_TYPE_DEADLINE_CHECK",
899 Self::SendReminder => "STEP_TYPE_SEND_REMINDER",
900 Self::CallWebhook => "STEP_TYPE_CALL_WEBHOOK",
901 Self::MarkMissed => "STEP_TYPE_MARK_MISSED",
902 Self::Escalate => "STEP_TYPE_ESCALATE",
903 }
904 }
905 /// Creates an enum from field names used in the ProtoBuf definition.
906 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
907 match value {
908 "STEP_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
909 "STEP_TYPE_SEND_NOTIFICATION" => Some(Self::SendNotification),
910 "STEP_TYPE_DEADLINE_CHECK" => Some(Self::DeadlineCheck),
911 "STEP_TYPE_SEND_REMINDER" => Some(Self::SendReminder),
912 "STEP_TYPE_CALL_WEBHOOK" => Some(Self::CallWebhook),
913 "STEP_TYPE_MARK_MISSED" => Some(Self::MarkMissed),
914 "STEP_TYPE_ESCALATE" => Some(Self::Escalate),
915 _ => None,
916 }
917 }
918}
919/// Condition that must be met for an escalation to fire.
920#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
921#[repr(i32)]
922pub enum EscalationCondition {
923 Unspecified = 0,
924 /// Escalate if the delivery has not been acknowledged.
925 IfNotAcked = 1,
926 /// Escalate if the campaign is still open (even if some deliveries are acknowledged).
927 IfNotClosed = 2,
928}
929impl EscalationCondition {
930 /// String value of the enum field names used in the ProtoBuf definition.
931 ///
932 /// The values are not transformed in any way and thus are considered stable
933 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
934 pub fn as_str_name(&self) -> &'static str {
935 match self {
936 Self::Unspecified => "ESCALATION_CONDITION_UNSPECIFIED",
937 Self::IfNotAcked => "ESCALATION_CONDITION_IF_NOT_ACKED",
938 Self::IfNotClosed => "ESCALATION_CONDITION_IF_NOT_CLOSED",
939 }
940 }
941 /// Creates an enum from field names used in the ProtoBuf definition.
942 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
943 match value {
944 "ESCALATION_CONDITION_UNSPECIFIED" => Some(Self::Unspecified),
945 "ESCALATION_CONDITION_IF_NOT_ACKED" => Some(Self::IfNotAcked),
946 "ESCALATION_CONDITION_IF_NOT_CLOSED" => Some(Self::IfNotClosed),
947 _ => None,
948 }
949 }
950}
951/// Type of escalation target.
952#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
953#[repr(i32)]
954pub enum EscalationTargetType {
955 Unspecified = 0,
956 /// Escalate to a specific user by ID.
957 User = 1,
958 /// Escalate to all members of a group.
959 Group = 2,
960 /// Escalate to the recipient's direct manager (resolved from manager_id at runtime).
961 Manager = 3,
962 /// Escalate to all users with a specific role in the org.
963 Role = 4,
964}
965impl EscalationTargetType {
966 /// String value of the enum field names used in the ProtoBuf definition.
967 ///
968 /// The values are not transformed in any way and thus are considered stable
969 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
970 pub fn as_str_name(&self) -> &'static str {
971 match self {
972 Self::Unspecified => "ESCALATION_TARGET_TYPE_UNSPECIFIED",
973 Self::User => "ESCALATION_TARGET_TYPE_USER",
974 Self::Group => "ESCALATION_TARGET_TYPE_GROUP",
975 Self::Manager => "ESCALATION_TARGET_TYPE_MANAGER",
976 Self::Role => "ESCALATION_TARGET_TYPE_ROLE",
977 }
978 }
979 /// Creates an enum from field names used in the ProtoBuf definition.
980 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
981 match value {
982 "ESCALATION_TARGET_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
983 "ESCALATION_TARGET_TYPE_USER" => Some(Self::User),
984 "ESCALATION_TARGET_TYPE_GROUP" => Some(Self::Group),
985 "ESCALATION_TARGET_TYPE_MANAGER" => Some(Self::Manager),
986 "ESCALATION_TARGET_TYPE_ROLE" => Some(Self::Role),
987 _ => None,
988 }
989 }
990}
991/// Behavior mode controlling what an escalation produces for its targets.
992#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
993#[repr(i32)]
994pub enum EscalateMode {
995 /// Default value; servers normalize this to ESCALATE_MODE_DELIVER.
996 Unspecified = 0,
997 /// Targets receive a delivery for the campaign just like primary recipients.
998 Deliver = 1,
999 /// Targets receive an out-of-band alert only; no delivery is created.
1000 AlertOnly = 2,
1001}
1002impl EscalateMode {
1003 /// String value of the enum field names used in the ProtoBuf definition.
1004 ///
1005 /// The values are not transformed in any way and thus are considered stable
1006 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
1007 pub fn as_str_name(&self) -> &'static str {
1008 match self {
1009 Self::Unspecified => "ESCALATE_MODE_UNSPECIFIED",
1010 Self::Deliver => "ESCALATE_MODE_DELIVER",
1011 Self::AlertOnly => "ESCALATE_MODE_ALERT_ONLY",
1012 }
1013 }
1014 /// Creates an enum from field names used in the ProtoBuf definition.
1015 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
1016 match value {
1017 "ESCALATE_MODE_UNSPECIFIED" => Some(Self::Unspecified),
1018 "ESCALATE_MODE_DELIVER" => Some(Self::Deliver),
1019 "ESCALATE_MODE_ALERT_ONLY" => Some(Self::AlertOnly),
1020 _ => None,
1021 }
1022 }
1023}
1024// ─── Messages ───────────────────────────────────────────────────────────────
1025
1026/// A scoped API key for programmatic access (MCP agents, service integrations).
1027#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1028pub struct ApiKey {
1029 /// Unique identifier.
1030 #[prost(string, tag="1")]
1031 pub id: ::prost::alloc::string::String,
1032 /// Human-friendly label (e.g. "MCP Production", "CI Pipeline").
1033 #[prost(string, tag="2")]
1034 pub name: ::prost::alloc::string::String,
1035 /// Displayable prefix of the key (e.g. "pidgr_k_abc12345").
1036 /// Used for identification — the full key is only returned on creation.
1037 #[prost(string, tag="3")]
1038 pub key_prefix: ::prost::alloc::string::String,
1039 /// Permissions granted to this key.
1040 #[prost(enumeration="Permission", repeated, tag="4")]
1041 pub permissions: ::prost::alloc::vec::Vec<i32>,
1042 /// When the key was created.
1043 #[prost(message, optional, tag="5")]
1044 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
1045 /// Last time the key was used to authenticate a request. Empty if never used.
1046 #[prost(message, optional, tag="6")]
1047 pub last_used_at: ::core::option::Option<::prost_types::Timestamp>,
1048 /// When the key expires. Empty means no expiration.
1049 #[prost(message, optional, tag="7")]
1050 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
1051 /// Type of this key (API key or SCIM token).
1052 /// Defaults to KEY_TYPE_API_KEY for existing keys.
1053 #[prost(enumeration="KeyType", tag="8")]
1054 pub key_type: i32,
1055}
1056/// Request to create a new API key.
1057#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1058pub struct CreateApiKeyRequest {
1059 /// Human-friendly label. Required, max 200 characters.
1060 #[prost(string, tag="1")]
1061 pub name: ::prost::alloc::string::String,
1062 /// Permissions to grant. Required, at least one.
1063 /// PERMISSION_UNSPECIFIED values are rejected.
1064 #[prost(enumeration="Permission", repeated, tag="2")]
1065 pub permissions: ::prost::alloc::vec::Vec<i32>,
1066 /// Optional expiration time. If omitted, the key does not expire.
1067 #[prost(message, optional, tag="3")]
1068 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
1069 /// Type of key to create. Defaults to KEY_TYPE_API_KEY.
1070 /// SCIM tokens use the "pidgr_scim_" prefix instead of "pidgr_k_".
1071 #[prost(enumeration="KeyType", tag="4")]
1072 pub key_type: i32,
1073}
1074/// Response after creating an API key.
1075/// IMPORTANT: The full key is only returned here — it cannot be retrieved later.
1076#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1077pub struct CreateApiKeyResponse {
1078 /// The created API key metadata.
1079 #[prost(message, optional, tag="1")]
1080 pub api_key: ::core::option::Option<ApiKey>,
1081 /// The full secret key value (e.g. "pidgr_k_abc12345...").
1082 /// Store this securely — it is not retrievable after this response.
1083 #[prost(string, tag="2")]
1084 pub key: ::prost::alloc::string::String,
1085}
1086/// Request to list all API keys in the caller's organization.
1087#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1088pub struct ListApiKeysRequest {
1089 /// Optional filter by key type. Unspecified returns all keys.
1090 #[prost(enumeration="KeyType", tag="1")]
1091 pub key_type: i32,
1092}
1093/// Response containing the organization's API keys.
1094#[derive(Clone, PartialEq, ::prost::Message)]
1095pub struct ListApiKeysResponse {
1096 /// All active (non-revoked) API keys. Full key values are not included.
1097 #[prost(message, repeated, tag="1")]
1098 pub api_keys: ::prost::alloc::vec::Vec<ApiKey>,
1099}
1100/// Request to revoke an API key.
1101#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1102pub struct RevokeApiKeyRequest {
1103 /// ID of the API key to revoke. Required.
1104 #[prost(string, tag="1")]
1105 pub api_key_id: ::prost::alloc::string::String,
1106}
1107/// Response after revoking an API key.
1108#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1109pub struct RevokeApiKeyResponse {
1110}
1111// ─── Enums ──────────────────────────────────────────────────────────────────
1112
1113/// Type of API key, distinguishing platform keys from SCIM provisioning tokens.
1114#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
1115#[repr(i32)]
1116pub enum KeyType {
1117 Unspecified = 0,
1118 ApiKey = 1,
1119 ScimToken = 2,
1120}
1121impl KeyType {
1122 /// String value of the enum field names used in the ProtoBuf definition.
1123 ///
1124 /// The values are not transformed in any way and thus are considered stable
1125 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
1126 pub fn as_str_name(&self) -> &'static str {
1127 match self {
1128 Self::Unspecified => "KEY_TYPE_UNSPECIFIED",
1129 Self::ApiKey => "KEY_TYPE_API_KEY",
1130 Self::ScimToken => "KEY_TYPE_SCIM_TOKEN",
1131 }
1132 }
1133 /// Creates an enum from field names used in the ProtoBuf definition.
1134 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
1135 match value {
1136 "KEY_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
1137 "KEY_TYPE_API_KEY" => Some(Self::ApiKey),
1138 "KEY_TYPE_SCIM_TOKEN" => Some(Self::ScimToken),
1139 _ => None,
1140 }
1141 }
1142}
1143// ─── Messages ───────────────────────────────────────────────────────────────
1144
1145/// Request to export all personal data associated with a user.
1146/// Auth: Requires JWT. Callable by the user themselves or an org admin.
1147#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1148pub struct ExportUserDataRequest {
1149 /// Internal user ID whose data is being exported.
1150 /// Constraints: UUID format (36 characters).
1151 #[prost(string, tag="1")]
1152 pub user_id: ::prost::alloc::string::String,
1153}
1154/// Response containing the export status and download location.
1155#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1156pub struct ExportUserDataResponse {
1157 /// Current status of the export request.
1158 #[prost(enumeration="PrivacyRequestStatus", tag="1")]
1159 pub status: i32,
1160 /// Pre-signed S3 URL to download the exported data (ZIP format).
1161 /// Only populated when status is COMPLETED.
1162 #[prost(string, tag="2")]
1163 pub result_url: ::prost::alloc::string::String,
1164 /// Unique identifier for this export request.
1165 /// Constraints: UUID format (36 characters).
1166 #[prost(string, tag="3")]
1167 pub export_id: ::prost::alloc::string::String,
1168}
1169/// Request to export all data associated with the calling organization
1170/// (GDPR Art. 20 data portability at the org level). The organization is
1171/// extracted from the JWT — it is never in the request message.
1172/// Auth: Requires JWT. Org admin only.
1173#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1174pub struct ExportOrgDataRequest {
1175}
1176/// Response containing the org export status and download location.
1177/// The export workflow assembles org configuration, users, campaigns,
1178/// deliveries, and audit events into an encrypted bundle delivered via a
1179/// pre-signed S3 URL.
1180#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1181pub struct ExportOrgDataResponse {
1182 /// Current status of the export request.
1183 #[prost(enumeration="PrivacyRequestStatus", tag="1")]
1184 pub status: i32,
1185 /// Pre-signed S3 URL to download the exported bundle (encrypted ZIP).
1186 /// Only populated when status is COMPLETED.
1187 #[prost(string, tag="2")]
1188 pub result_url: ::prost::alloc::string::String,
1189 /// Unique identifier for this export request.
1190 /// Constraints: UUID format (36 characters).
1191 #[prost(string, tag="3")]
1192 pub export_id: ::prost::alloc::string::String,
1193}
1194/// Request to delete or anonymize all personal data associated with a user.
1195/// Auth: Requires JWT. Admin only.
1196#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1197pub struct DeleteUserDataRequest {
1198 /// Internal user ID whose data is being deleted.
1199 /// Constraints: UUID format (36 characters).
1200 #[prost(string, tag="1")]
1201 pub user_id: ::prost::alloc::string::String,
1202 /// When true, PII is replaced with placeholders instead of hard-deleted.
1203 /// This preserves audit trail integrity while removing personal data.
1204 #[prost(bool, tag="2")]
1205 pub anonymize: bool,
1206}
1207/// Response confirming the deletion request.
1208#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1209pub struct DeleteUserDataResponse {
1210 /// Current status of the deletion request.
1211 #[prost(enumeration="PrivacyRequestStatus", tag="1")]
1212 pub status: i32,
1213 /// Timestamp when deletion was completed (or scheduled).
1214 /// Only populated when status is COMPLETED.
1215 #[prost(message, optional, tag="2")]
1216 pub deleted_at: ::core::option::Option<::prost_types::Timestamp>,
1217 /// Unique identifier for this deletion request.
1218 #[prost(string, tag="3")]
1219 pub request_id: ::prost::alloc::string::String,
1220}
1221/// Request to list privacy requests for the organization.
1222/// Auth: Requires JWT. Admin only.
1223#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1224pub struct ListPrivacyRequestsRequest {
1225 /// Maximum number of results per page.
1226 /// Constraints: 1–100, default 25.
1227 #[prost(int32, tag="1")]
1228 pub page_size: i32,
1229 /// Continuation token from a previous response.
1230 #[prost(string, tag="2")]
1231 pub page_token: ::prost::alloc::string::String,
1232 /// Filter by request type (export, delete, rectify, restrict). Empty = all.
1233 #[prost(string, tag="3")]
1234 pub request_type: ::prost::alloc::string::String,
1235 /// Filter by status. UNSPECIFIED = all.
1236 #[prost(enumeration="PrivacyRequestStatus", tag="4")]
1237 pub status: i32,
1238}
1239/// Response containing privacy requests.
1240#[derive(Clone, PartialEq, ::prost::Message)]
1241pub struct ListPrivacyRequestsResponse {
1242 /// The privacy requests matching the filters.
1243 #[prost(message, repeated, tag="1")]
1244 pub requests: ::prost::alloc::vec::Vec<PrivacyRequest>,
1245 /// Token for the next page. Empty if no more results.
1246 #[prost(string, tag="2")]
1247 pub next_page_token: ::prost::alloc::string::String,
1248}
1249/// A privacy request record.
1250#[derive(Clone, PartialEq, ::prost::Message)]
1251pub struct PrivacyRequest {
1252 /// Unique identifier.
1253 #[prost(string, tag="1")]
1254 pub id: ::prost::alloc::string::String,
1255 /// The user this request applies to.
1256 #[prost(string, tag="2")]
1257 pub user_id: ::prost::alloc::string::String,
1258 /// Email of the target user.
1259 #[prost(string, tag="3")]
1260 pub user_email: ::prost::alloc::string::String,
1261 /// Type of request (export, delete, rectify, restrict).
1262 #[prost(string, tag="4")]
1263 pub request_type: ::prost::alloc::string::String,
1264 /// Current status.
1265 #[prost(enumeration="PrivacyRequestStatus", tag="5")]
1266 pub status: i32,
1267 /// Whether to anonymize (true) or hard-delete (false). Only for delete requests.
1268 #[prost(bool, tag="6")]
1269 pub anonymize: bool,
1270 /// Email of the admin who initiated this request.
1271 #[prost(string, tag="7")]
1272 pub requested_by_email: ::prost::alloc::string::String,
1273 /// When the request was created.
1274 #[prost(message, optional, tag="8")]
1275 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
1276 /// When the request was completed (if applicable).
1277 #[prost(message, optional, tag="9")]
1278 pub completed_at: ::core::option::Option<::prost_types::Timestamp>,
1279 /// Additional metadata (JSON).
1280 #[prost(map="string, string", tag="10")]
1281 pub metadata: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
1282}
1283/// Request to cancel a pending deletion.
1284/// Auth: Requires JWT. Admin only.
1285#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1286pub struct CancelDeletionRequest {
1287 /// The privacy request ID to cancel.
1288 #[prost(string, tag="1")]
1289 pub request_id: ::prost::alloc::string::String,
1290 /// Admin must type the target user's email to confirm.
1291 #[prost(string, tag="2")]
1292 pub confirmation_email: ::prost::alloc::string::String,
1293}
1294/// Response confirming the cancellation.
1295#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1296pub struct CancelDeletionResponse {
1297 /// Updated status (should be FAILED with reason cancelled).
1298 #[prost(enumeration="PrivacyRequestStatus", tag="1")]
1299 pub status: i32,
1300}
1301/// Request to skip the grace period and delete immediately.
1302/// Auth: Requires JWT. Admin only.
1303#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1304pub struct ImmediateDeleteRequest {
1305 /// The privacy request ID to expedite.
1306 #[prost(string, tag="1")]
1307 pub request_id: ::prost::alloc::string::String,
1308 /// Admin must type the target user's email to confirm.
1309 #[prost(string, tag="2")]
1310 pub confirmation_email: ::prost::alloc::string::String,
1311}
1312/// Response confirming the immediate deletion was triggered.
1313#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1314pub struct ImmediateDeleteResponse {
1315 /// Updated status (should be PROCESSING).
1316 #[prost(enumeration="PrivacyRequestStatus", tag="1")]
1317 pub status: i32,
1318}
1319/// Request to correct personal data for a user.
1320/// Auth: Requires JWT. Callable by the user themselves or an org admin.
1321#[derive(Clone, PartialEq, ::prost::Message)]
1322pub struct RectifyUserDataRequest {
1323 /// Internal user ID whose data is being corrected.
1324 /// Constraints: UUID format (36 characters).
1325 #[prost(string, tag="1")]
1326 pub user_id: ::prost::alloc::string::String,
1327 /// Map of field names to corrected values.
1328 /// Corrections are propagated to all stored locations.
1329 /// Constraints: Max 50 corrections per request.
1330 #[prost(map="string, string", tag="2")]
1331 pub corrections: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
1332}
1333/// Response listing which fields were successfully corrected.
1334#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1335pub struct RectifyUserDataResponse {
1336 /// Names of fields that were rectified.
1337 #[prost(string, repeated, tag="1")]
1338 pub rectified_fields: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
1339}
1340/// Request to restrict or unrestrict processing for a user.
1341/// Auth: Requires JWT. Admin only.
1342#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1343pub struct RestrictProcessingRequest {
1344 /// Internal user ID whose processing is being restricted.
1345 /// Constraints: UUID format (36 characters).
1346 #[prost(string, tag="1")]
1347 pub user_id: ::prost::alloc::string::String,
1348 /// When true, processing is restricted. When false, restriction is lifted.
1349 #[prost(bool, tag="2")]
1350 pub restricted: bool,
1351}
1352/// Response confirming the processing restriction status.
1353#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1354pub struct RestrictProcessingResponse {
1355 /// Current restriction status.
1356 #[prost(bool, tag="1")]
1357 pub restricted: bool,
1358 /// Timestamp when the restriction was applied or removed.
1359 #[prost(message, optional, tag="2")]
1360 pub restricted_at: ::core::option::Option<::prost_types::Timestamp>,
1361}
1362/// Request to confirm whether personal data exists for a user.
1363/// LGPD-specific: confirmação de existência (Art. 18, I).
1364/// Auth: Requires JWT. Admin only.
1365#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1366pub struct GetDataExistenceConfirmationRequest {
1367 /// Internal user ID to check.
1368 /// Constraints: UUID format (36 characters).
1369 #[prost(string, tag="1")]
1370 pub user_id: ::prost::alloc::string::String,
1371}
1372/// Response confirming data existence and listing data categories.
1373#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1374pub struct GetDataExistenceConfirmationResponse {
1375 /// Whether any personal data exists for this user.
1376 #[prost(bool, tag="1")]
1377 pub exists: bool,
1378 /// Categories of data stored (e.g., "profile", "deliveries", "analytics").
1379 #[prost(string, repeated, tag="2")]
1380 pub data_categories: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
1381}
1382/// Request to list the calling user's own privacy requests.
1383/// Auth: Requires JWT. No admin permission required — returns only the caller's requests.
1384#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1385pub struct ListMyPrivacyRequestsRequest {
1386 /// Maximum number of results per page.
1387 /// Constraints: 1–100, default 25.
1388 #[prost(int32, tag="1")]
1389 pub page_size: i32,
1390 /// Continuation token from a previous response.
1391 #[prost(string, tag="2")]
1392 pub page_token: ::prost::alloc::string::String,
1393 /// Filter by request type (export, rectify). Empty = all.
1394 #[prost(string, tag="3")]
1395 pub request_type: ::prost::alloc::string::String,
1396 /// Filter by status. UNSPECIFIED = all.
1397 #[prost(enumeration="PrivacyRequestStatus", tag="4")]
1398 pub status: i32,
1399}
1400/// Response containing the calling user's privacy requests.
1401#[derive(Clone, PartialEq, ::prost::Message)]
1402pub struct ListMyPrivacyRequestsResponse {
1403 /// The privacy requests belonging to the calling user.
1404 #[prost(message, repeated, tag="1")]
1405 pub requests: ::prost::alloc::vec::Vec<PrivacyRequest>,
1406 /// Token for the next page. Empty if no more results.
1407 #[prost(string, tag="2")]
1408 pub next_page_token: ::prost::alloc::string::String,
1409}
1410/// A security incident that touched the calling organization. Org-facing
1411/// read-only subset of the staff-side incident record — internal triage
1412/// fields (detector signal, classifier identity, evidence pointers) are
1413/// intentionally not exposed.
1414#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1415pub struct OrgSecurityIncident {
1416 /// Unique identifier for the incident.
1417 /// Constraints: UUID format (36 characters).
1418 #[prost(string, tag="1")]
1419 pub id: ::prost::alloc::string::String,
1420 /// When the observability platform detected the incident. The canonical
1421 /// anchor for the 72-hour GDPR Art. 33 notification clock.
1422 #[prost(message, optional, tag="2")]
1423 pub detected_at: ::core::option::Option<::prost_types::Timestamp>,
1424 /// Detector-assigned severity.
1425 #[prost(enumeration="SecurityIncidentSeverity", tag="3")]
1426 pub severity: i32,
1427 /// Legal classification verdict. PENDING until staff triage completes.
1428 #[prost(enumeration="SecurityIncidentClassification", tag="4")]
1429 pub classification: i32,
1430 /// When the regulator was notified. Empty if no notification was required
1431 /// or it has not happened yet.
1432 #[prost(message, optional, tag="5")]
1433 pub notified_at: ::core::option::Option<::prost_types::Timestamp>,
1434 /// When the incident was resolved. Empty while still open.
1435 #[prost(message, optional, tag="6")]
1436 pub resolved_at: ::core::option::Option<::prost_types::Timestamp>,
1437}
1438/// Request to list security incidents that touched the calling organization.
1439/// The organization is extracted from the JWT — it is never in the request.
1440/// Auth: Requires JWT. Admin only.
1441#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1442pub struct ListOrgSecurityIncidentsRequest {
1443 /// Maximum number of results per page.
1444 /// Constraints: 1–100, default 25.
1445 #[prost(int32, tag="1")]
1446 pub page_size: i32,
1447 /// Continuation token from a previous response.
1448 #[prost(string, tag="2")]
1449 pub page_token: ::prost::alloc::string::String,
1450}
1451/// Response containing the organization's security incident feed.
1452#[derive(Clone, PartialEq, ::prost::Message)]
1453pub struct ListOrgSecurityIncidentsResponse {
1454 /// Incidents that touched the organization, ordered by detected_at
1455 /// descending (newest first).
1456 #[prost(message, repeated, tag="1")]
1457 pub incidents: ::prost::alloc::vec::Vec<OrgSecurityIncident>,
1458 /// Token for the next page. Empty if no more results.
1459 #[prost(string, tag="2")]
1460 pub next_page_token: ::prost::alloc::string::String,
1461}
1462// ─── Enums ──────────────────────────────────────────────────────────────────
1463
1464/// Status of a privacy request (export, delete, rectify, restrict).
1465#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
1466#[repr(i32)]
1467pub enum PrivacyRequestStatus {
1468 /// Default value; should not be used explicitly.
1469 Unspecified = 0,
1470 /// Request has been created but not yet started.
1471 Pending = 1,
1472 /// Request is currently being processed.
1473 Processing = 2,
1474 /// Request completed successfully.
1475 Completed = 3,
1476 /// Request failed during processing.
1477 Failed = 4,
1478}
1479impl PrivacyRequestStatus {
1480 /// String value of the enum field names used in the ProtoBuf definition.
1481 ///
1482 /// The values are not transformed in any way and thus are considered stable
1483 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
1484 pub fn as_str_name(&self) -> &'static str {
1485 match self {
1486 Self::Unspecified => "PRIVACY_REQUEST_STATUS_UNSPECIFIED",
1487 Self::Pending => "PRIVACY_REQUEST_STATUS_PENDING",
1488 Self::Processing => "PRIVACY_REQUEST_STATUS_PROCESSING",
1489 Self::Completed => "PRIVACY_REQUEST_STATUS_COMPLETED",
1490 Self::Failed => "PRIVACY_REQUEST_STATUS_FAILED",
1491 }
1492 }
1493 /// Creates an enum from field names used in the ProtoBuf definition.
1494 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
1495 match value {
1496 "PRIVACY_REQUEST_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
1497 "PRIVACY_REQUEST_STATUS_PENDING" => Some(Self::Pending),
1498 "PRIVACY_REQUEST_STATUS_PROCESSING" => Some(Self::Processing),
1499 "PRIVACY_REQUEST_STATUS_COMPLETED" => Some(Self::Completed),
1500 "PRIVACY_REQUEST_STATUS_FAILED" => Some(Self::Failed),
1501 _ => None,
1502 }
1503 }
1504}
1505/// Detector-assigned severity of a security incident. Mirrors the staff-side
1506/// incident taxonomy; the org feed exposes the same values read-only.
1507#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
1508#[repr(i32)]
1509pub enum SecurityIncidentSeverity {
1510 /// Default value; should not be used explicitly.
1511 Unspecified = 0,
1512 /// Informational signal; no action expected.
1513 Info = 1,
1514 /// Anomalous signal under investigation.
1515 Warn = 2,
1516 /// Confirmed or suspected breach-grade signal.
1517 Breach = 3,
1518}
1519impl SecurityIncidentSeverity {
1520 /// String value of the enum field names used in the ProtoBuf definition.
1521 ///
1522 /// The values are not transformed in any way and thus are considered stable
1523 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
1524 pub fn as_str_name(&self) -> &'static str {
1525 match self {
1526 Self::Unspecified => "SECURITY_INCIDENT_SEVERITY_UNSPECIFIED",
1527 Self::Info => "SECURITY_INCIDENT_SEVERITY_INFO",
1528 Self::Warn => "SECURITY_INCIDENT_SEVERITY_WARN",
1529 Self::Breach => "SECURITY_INCIDENT_SEVERITY_BREACH",
1530 }
1531 }
1532 /// Creates an enum from field names used in the ProtoBuf definition.
1533 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
1534 match value {
1535 "SECURITY_INCIDENT_SEVERITY_UNSPECIFIED" => Some(Self::Unspecified),
1536 "SECURITY_INCIDENT_SEVERITY_INFO" => Some(Self::Info),
1537 "SECURITY_INCIDENT_SEVERITY_WARN" => Some(Self::Warn),
1538 "SECURITY_INCIDENT_SEVERITY_BREACH" => Some(Self::Breach),
1539 _ => None,
1540 }
1541 }
1542}
1543/// Legal classification verdict recorded by platform staff during triage.
1544/// Mirrors the staff-side incident taxonomy; immutable once set.
1545#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
1546#[repr(i32)]
1547pub enum SecurityIncidentClassification {
1548 /// Default value; should not be used explicitly.
1549 Unspecified = 0,
1550 /// Queued for triage; no verdict recorded yet.
1551 Pending = 1,
1552 /// Triage concluded the incident is not a breach.
1553 NotBreach = 2,
1554 /// Operational incident with no personal data involved.
1555 OperationalOnly = 10,
1556 /// Personal data breach (GDPR Art. 33 notification clock running).
1557 PersonalDataBreach = 11,
1558 /// Personal data breach with high risk to data subjects (GDPR Art. 34).
1559 PersonalDataBreachHighRisk = 12,
1560}
1561impl SecurityIncidentClassification {
1562 /// String value of the enum field names used in the ProtoBuf definition.
1563 ///
1564 /// The values are not transformed in any way and thus are considered stable
1565 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
1566 pub fn as_str_name(&self) -> &'static str {
1567 match self {
1568 Self::Unspecified => "SECURITY_INCIDENT_CLASSIFICATION_UNSPECIFIED",
1569 Self::Pending => "SECURITY_INCIDENT_CLASSIFICATION_PENDING",
1570 Self::NotBreach => "SECURITY_INCIDENT_CLASSIFICATION_NOT_BREACH",
1571 Self::OperationalOnly => "SECURITY_INCIDENT_CLASSIFICATION_OPERATIONAL_ONLY",
1572 Self::PersonalDataBreach => "SECURITY_INCIDENT_CLASSIFICATION_PERSONAL_DATA_BREACH",
1573 Self::PersonalDataBreachHighRisk => "SECURITY_INCIDENT_CLASSIFICATION_PERSONAL_DATA_BREACH_HIGH_RISK",
1574 }
1575 }
1576 /// Creates an enum from field names used in the ProtoBuf definition.
1577 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
1578 match value {
1579 "SECURITY_INCIDENT_CLASSIFICATION_UNSPECIFIED" => Some(Self::Unspecified),
1580 "SECURITY_INCIDENT_CLASSIFICATION_PENDING" => Some(Self::Pending),
1581 "SECURITY_INCIDENT_CLASSIFICATION_NOT_BREACH" => Some(Self::NotBreach),
1582 "SECURITY_INCIDENT_CLASSIFICATION_OPERATIONAL_ONLY" => Some(Self::OperationalOnly),
1583 "SECURITY_INCIDENT_CLASSIFICATION_PERSONAL_DATA_BREACH" => Some(Self::PersonalDataBreach),
1584 "SECURITY_INCIDENT_CLASSIFICATION_PERSONAL_DATA_BREACH_HIGH_RISK" => Some(Self::PersonalDataBreachHighRisk),
1585 _ => None,
1586 }
1587 }
1588}
1589// ─── Messages ───────────────────────────────────────────────────────────────
1590
1591/// An immutable audit event capturing a significant platform action.
1592/// Audit events are append-only — they cannot be updated or deleted.
1593#[derive(Clone, PartialEq, ::prost::Message)]
1594pub struct AuditEvent {
1595 /// Unique identifier for this audit event.
1596 /// Constraints: UUID format (36 characters).
1597 #[prost(string, tag="1")]
1598 pub id: ::prost::alloc::string::String,
1599 /// Organization in which the event occurred.
1600 /// Constraints: UUID format (36 characters).
1601 #[prost(string, tag="2")]
1602 pub org_id: ::prost::alloc::string::String,
1603 /// User who performed the action. Empty for system-initiated events.
1604 /// Constraints: UUID format (36 characters) when present.
1605 #[prost(string, tag="3")]
1606 pub actor_id: ::prost::alloc::string::String,
1607 /// Type of action that was performed.
1608 #[prost(enumeration="AuditEventType", tag="4")]
1609 pub event_type: i32,
1610 /// Type of entity affected (e.g., "campaign", "user", "template").
1611 /// Constraints: Max length 50 characters.
1612 #[prost(string, tag="5")]
1613 pub entity_type: ::prost::alloc::string::String,
1614 /// Identifier of the entity affected.
1615 /// Constraints: UUID format (36 characters).
1616 #[prost(string, tag="6")]
1617 pub entity_id: ::prost::alloc::string::String,
1618 /// Additional context about the event (e.g., old/new values for changes).
1619 /// Constraints: Max 20 key-value pairs, keys max 50 chars, values max 500 chars.
1620 #[prost(map="string, string", tag="7")]
1621 pub metadata: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
1622 /// True when this event is synthetic (artificially injected) data — used for
1623 /// demos, sandbox testing, or issue reproduction — rather than the record of
1624 /// a real user action.
1625 #[prost(bool, tag="8")]
1626 pub synthetic: bool,
1627 /// Timestamp when the event was recorded.
1628 #[prost(message, optional, tag="10")]
1629 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
1630}
1631/// Request to list audit events with optional filters.
1632/// Auth: Requires JWT. Admin only.
1633#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1634pub struct ListAuditEventsRequest {
1635 /// Pagination token from a previous response.
1636 #[prost(string, tag="1")]
1637 pub page_token: ::prost::alloc::string::String,
1638 /// Maximum number of events to return.
1639 /// Constraints: Min 1, max 100. Default 50.
1640 #[prost(int32, tag="2")]
1641 pub page_size: i32,
1642 /// Optional filter: only return events of this type.
1643 #[prost(enumeration="AuditEventType", tag="3")]
1644 pub event_type: i32,
1645 /// Optional filter: only return events by this actor.
1646 /// Constraints: UUID format (36 characters).
1647 #[prost(string, tag="4")]
1648 pub actor_id: ::prost::alloc::string::String,
1649 /// Optional filter: events after this timestamp (inclusive).
1650 #[prost(message, optional, tag="5")]
1651 pub start_time: ::core::option::Option<::prost_types::Timestamp>,
1652 /// Optional filter: events before this timestamp (exclusive).
1653 #[prost(message, optional, tag="6")]
1654 pub end_time: ::core::option::Option<::prost_types::Timestamp>,
1655}
1656/// Response containing a paginated list of audit events.
1657#[derive(Clone, PartialEq, ::prost::Message)]
1658pub struct ListAuditEventsResponse {
1659 /// Audit events matching the request filters.
1660 #[prost(message, repeated, tag="1")]
1661 pub events: ::prost::alloc::vec::Vec<AuditEvent>,
1662 /// Token for fetching the next page. Empty when no more events.
1663 #[prost(string, tag="2")]
1664 pub next_page_token: ::prost::alloc::string::String,
1665}
1666/// Request to export the audit trail to S3 in a specified format.
1667/// Auth: Requires JWT. Admin only.
1668#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1669pub struct ExportAuditTrailRequest {
1670 /// Export format.
1671 #[prost(enumeration="AuditExportFormat", tag="1")]
1672 pub format: i32,
1673 /// Optional: export events after this timestamp.
1674 #[prost(message, optional, tag="2")]
1675 pub start_time: ::core::option::Option<::prost_types::Timestamp>,
1676 /// Optional: export events before this timestamp.
1677 #[prost(message, optional, tag="3")]
1678 pub end_time: ::core::option::Option<::prost_types::Timestamp>,
1679}
1680/// Response containing the export download URL.
1681#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1682pub struct ExportAuditTrailResponse {
1683 /// Pre-signed S3 URL to download the exported audit trail.
1684 /// Only populated when status is COMPLETED.
1685 #[prost(string, tag="1")]
1686 pub export_url: ::prost::alloc::string::String,
1687 /// Current status of the export request.
1688 #[prost(enumeration="PrivacyRequestStatus", tag="2")]
1689 pub status: i32,
1690}
1691/// A persistent record of an audit trail export request.
1692#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1693pub struct AuditExport {
1694 /// Unique identifier.
1695 #[prost(string, tag="1")]
1696 pub id: ::prost::alloc::string::String,
1697 /// Export format (csv, json).
1698 #[prost(string, tag="2")]
1699 pub format: ::prost::alloc::string::String,
1700 /// Current status.
1701 #[prost(enumeration="PrivacyRequestStatus", tag="3")]
1702 pub status: i32,
1703 /// Pre-signed download URL. Only populated when status is COMPLETED.
1704 #[prost(string, tag="4")]
1705 pub result_url: ::prost::alloc::string::String,
1706 /// Error message if the export failed.
1707 #[prost(string, tag="5")]
1708 pub error_message: ::prost::alloc::string::String,
1709 /// Email of the admin who requested the export.
1710 #[prost(string, tag="6")]
1711 pub requested_by_email: ::prost::alloc::string::String,
1712 /// When the export was requested.
1713 #[prost(message, optional, tag="7")]
1714 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
1715 /// When the export completed (if applicable).
1716 #[prost(message, optional, tag="8")]
1717 pub completed_at: ::core::option::Option<::prost_types::Timestamp>,
1718}
1719/// Request to list audit export history.
1720/// Auth: Requires JWT. Admin only.
1721#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1722pub struct ListAuditExportsRequest {
1723}
1724/// Response containing the list of audit exports.
1725#[derive(Clone, PartialEq, ::prost::Message)]
1726pub struct ListAuditExportsResponse {
1727 /// Audit export records, newest first.
1728 #[prost(message, repeated, tag="1")]
1729 pub exports: ::prost::alloc::vec::Vec<AuditExport>,
1730}
1731/// Request to append a single audit event from an internal service.
1732///
1733/// Auth: INTERNAL-mTLS ONLY. Unlike the read-side RPCs which authenticate
1734/// via Cognito JWT and infer `org_id` from the caller's claim, this RPC is
1735/// invoked by sibling services (e.g. pidgr-integrations) over the internal
1736/// mTLS mesh and therefore carries `org_id` in the request payload. The
1737/// server MUST reject any caller presenting only a JWT.
1738#[derive(Clone, PartialEq, ::prost::Message)]
1739pub struct AppendRequest {
1740 /// String form of the event type. Sibling services use a stable string
1741 /// identifier (e.g. "REACHABILITY_UPSERT", "REACHABILITY_REMOVE") so a
1742 /// new event type does not require a coordinated proto release across
1743 /// every internal service before it can be recorded. The audit server
1744 /// is responsible for mapping the string into its internal taxonomy.
1745 #[prost(string, tag="1")]
1746 pub event_type: ::prost::alloc::string::String,
1747 /// Organization in which the event occurred. UUID.
1748 #[prost(string, tag="2")]
1749 pub org_id: ::prost::alloc::string::String,
1750 /// User the audit event is about, if applicable. UUID. Unset when the
1751 /// event is not subject-bound (e.g. an org-wide policy change).
1752 #[prost(string, optional, tag="3")]
1753 pub subject_user_id: ::core::option::Option<::prost::alloc::string::String>,
1754 /// Actor who initiated the action, if any. UUID. Unset for system-initiated
1755 /// or sibling-service-initiated events.
1756 #[prost(string, optional, tag="4")]
1757 pub actor_id: ::core::option::Option<::prost::alloc::string::String>,
1758 /// Structured event-specific payload. Used in lieu of the rigid
1759 /// `map<string, string> metadata` on `AuditEvent` so sibling services
1760 /// can record nested objects (e.g. a `prefetch_signals` block) without
1761 /// string-encoding every value. Servers SHOULD redact PII before persist
1762 /// and MUST NOT log this field at INFO or above. Sensitive cryptographic
1763 /// material (plaintext identifiers, envelope ciphertext, raw HMAC keys)
1764 /// MUST NOT be placed here.
1765 #[prost(message, optional, tag="5")]
1766 pub details: ::core::option::Option<::prost_types::Struct>,
1767}
1768#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1769pub struct AppendResponse {
1770 /// Server-assigned audit event identifier (UUID).
1771 #[prost(string, tag="1")]
1772 pub event_id: ::prost::alloc::string::String,
1773}
1774// ─── Enums ──────────────────────────────────────────────────────────────────
1775
1776/// Type of auditable platform action.
1777#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
1778#[repr(i32)]
1779pub enum AuditEventType {
1780 /// Default value; should not be used explicitly.
1781 Unspecified = 0,
1782 /// ── Campaign lifecycle ───────────────────────────────────────────────────
1783 /// A campaign was created.
1784 CampaignCreated = 1,
1785 /// A message was sent to a recipient.
1786 MessageSent = 2,
1787 /// A message was opened by a recipient.
1788 MessageOpened = 3,
1789 /// A recipient acknowledged a campaign.
1790 AckRegistered = 4,
1791 /// An escalation was triggered by the workflow.
1792 EscalationExecuted = 5,
1793 /// A campaign was started.
1794 CampaignStarted = 12,
1795 /// A campaign was cancelled.
1796 CampaignCancelled = 13,
1797 /// A campaign was updated.
1798 CampaignUpdated = 14,
1799 /// ── User lifecycle ───────────────────────────────────────────────────────
1800 /// A user was invited to the organization.
1801 UserInvited = 6,
1802 /// A user was deactivated.
1803 UserDeactivated = 7,
1804 /// A user was reactivated.
1805 UserReactivated = 15,
1806 /// A user's role was changed (assigned to a different role).
1807 RoleChanged = 10,
1808 /// A user's invite was revoked.
1809 InviteRevoked = 16,
1810 /// A user's profile was updated.
1811 ProfileUpdated = 17,
1812 /// A user's settings were updated.
1813 SettingsUpdated = 18,
1814 /// A user enrolled a passkey.
1815 PasskeyEnrolled = 19,
1816 /// ── GDPR / Privacy ──────────────────────────────────────────────────────
1817 /// A data export was requested (GDPR Art. 15).
1818 DataExportRequested = 8,
1819 /// A data deletion was requested (GDPR Art. 17).
1820 DataDeletionRequested = 9,
1821 /// User data was rectified (GDPR Art. 16).
1822 DataRectified = 20,
1823 /// Data processing was restricted (GDPR Art. 18).
1824 ProcessingRestricted = 21,
1825 /// A scheduled deletion was cancelled.
1826 DeletionCancelled = 22,
1827 /// An immediate deletion was executed.
1828 DeletionImmediate = 23,
1829 /// ── Organization / SSO ───────────────────────────────────────────────────
1830 /// An SSO provider was configured.
1831 SsoConfigured = 11,
1832 /// An SSO provider was created.
1833 SsoProviderCreated = 24,
1834 /// An SSO provider was deleted.
1835 SsoProviderDeleted = 25,
1836 /// Organization settings were updated.
1837 OrgUpdated = 26,
1838 /// ── Roles ────────────────────────────────────────────────────────────────
1839 /// A role was created.
1840 RoleCreated = 27,
1841 /// A role's name or permissions were updated.
1842 RoleUpdated = 28,
1843 /// A role was deleted.
1844 RoleDeleted = 29,
1845 /// ── Templates ────────────────────────────────────────────────────────────
1846 /// A template was created.
1847 TemplateCreated = 30,
1848 /// A template was updated.
1849 TemplateUpdated = 31,
1850 /// ── API Keys ─────────────────────────────────────────────────────────────
1851 /// An API key was created.
1852 ApiKeyCreated = 32,
1853 /// An API key was revoked.
1854 ApiKeyRevoked = 33,
1855 /// ── Invite Links ─────────────────────────────────────────────────────────
1856 /// An invite link was created.
1857 InviteLinkCreated = 34,
1858 /// An invite link was revoked.
1859 InviteLinkRevoked = 35,
1860 /// ── Groups ───────────────────────────────────────────────────────────────
1861 /// A group was created.
1862 GroupCreated = 36,
1863 /// A group was updated.
1864 GroupUpdated = 37,
1865 /// A group was deleted.
1866 GroupDeleted = 38,
1867 /// Members were added to a group.
1868 GroupMembersAdded = 39,
1869 /// Members were removed from a group.
1870 GroupMembersRemoved = 40,
1871 /// ── Teams ────────────────────────────────────────────────────────────────
1872 /// A team was created.
1873 TeamCreated = 41,
1874 /// A team was updated.
1875 TeamUpdated = 42,
1876 /// A team was deleted.
1877 TeamDeleted = 43,
1878 /// Members were added to a team.
1879 TeamMembersAdded = 44,
1880 /// Members were removed from a team.
1881 TeamMembersRemoved = 45,
1882 /// ── SCIM Provisioning ───────────────────────────────────────────────────
1883 /// A user was provisioned via SCIM.
1884 ScimUserProvisioned = 46,
1885 /// A user was deprovisioned via SCIM.
1886 ScimUserDeprovisioned = 47,
1887 /// A user was updated via SCIM.
1888 ScimUserUpdated = 48,
1889 /// ── Translations ────────────────────────────────────────────────────────
1890 /// A template translation was created.
1891 TranslationCreated = 49,
1892 /// A template translation was approved.
1893 TranslationApproved = 50,
1894 /// ── Sandbox Orgs ────────────────────────────────────────────────────────
1895 /// A sandbox organization was created.
1896 SandboxCreated = 51,
1897 /// A sandbox organization expired and was deleted.
1898 SandboxExpired = 52,
1899 /// ── AI/Insights ─────────────────────────────────────────────────────────
1900 /// An AI prediction was served and logged (EU AI Act Art. 12).
1901 AiPredictionLogged = 53,
1902 /// The ML pipeline (archetype clustering + enrichment) was manually triggered.
1903 MlPipelineTriggered = 54,
1904 /// Per-group archetype clustering was manually triggered.
1905 ArchetypeClusteringTriggered = 55,
1906 /// ── Org lifecycle ───────────────────────────────────────────────────────
1907 /// An organization was created.
1908 OrgCreated = 56,
1909 /// An organization was deleted (sandbox cleanup or manual deletion).
1910 OrgDeleted = 57,
1911 /// ── Reachability registry (pidgr-integrations) ──────────────────────────
1912 /// A reachability identifier (email, phone, Slack ID, etc.) was upserted.
1913 /// GDPR-relevant per Chikorita audit classification.
1914 ReachabilityUpsert = 58,
1915 /// A reachability identifier was removed. GDPR Art. 17 "right to erasure"
1916 /// event; written BEFORE the registry row is deleted per Recital 30.
1917 ReachabilityRemove = 59,
1918}
1919impl AuditEventType {
1920 /// String value of the enum field names used in the ProtoBuf definition.
1921 ///
1922 /// The values are not transformed in any way and thus are considered stable
1923 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
1924 pub fn as_str_name(&self) -> &'static str {
1925 match self {
1926 Self::Unspecified => "AUDIT_EVENT_TYPE_UNSPECIFIED",
1927 Self::CampaignCreated => "AUDIT_EVENT_TYPE_CAMPAIGN_CREATED",
1928 Self::MessageSent => "AUDIT_EVENT_TYPE_MESSAGE_SENT",
1929 Self::MessageOpened => "AUDIT_EVENT_TYPE_MESSAGE_OPENED",
1930 Self::AckRegistered => "AUDIT_EVENT_TYPE_ACK_REGISTERED",
1931 Self::EscalationExecuted => "AUDIT_EVENT_TYPE_ESCALATION_EXECUTED",
1932 Self::CampaignStarted => "AUDIT_EVENT_TYPE_CAMPAIGN_STARTED",
1933 Self::CampaignCancelled => "AUDIT_EVENT_TYPE_CAMPAIGN_CANCELLED",
1934 Self::CampaignUpdated => "AUDIT_EVENT_TYPE_CAMPAIGN_UPDATED",
1935 Self::UserInvited => "AUDIT_EVENT_TYPE_USER_INVITED",
1936 Self::UserDeactivated => "AUDIT_EVENT_TYPE_USER_DEACTIVATED",
1937 Self::UserReactivated => "AUDIT_EVENT_TYPE_USER_REACTIVATED",
1938 Self::RoleChanged => "AUDIT_EVENT_TYPE_ROLE_CHANGED",
1939 Self::InviteRevoked => "AUDIT_EVENT_TYPE_INVITE_REVOKED",
1940 Self::ProfileUpdated => "AUDIT_EVENT_TYPE_PROFILE_UPDATED",
1941 Self::SettingsUpdated => "AUDIT_EVENT_TYPE_SETTINGS_UPDATED",
1942 Self::PasskeyEnrolled => "AUDIT_EVENT_TYPE_PASSKEY_ENROLLED",
1943 Self::DataExportRequested => "AUDIT_EVENT_TYPE_DATA_EXPORT_REQUESTED",
1944 Self::DataDeletionRequested => "AUDIT_EVENT_TYPE_DATA_DELETION_REQUESTED",
1945 Self::DataRectified => "AUDIT_EVENT_TYPE_DATA_RECTIFIED",
1946 Self::ProcessingRestricted => "AUDIT_EVENT_TYPE_PROCESSING_RESTRICTED",
1947 Self::DeletionCancelled => "AUDIT_EVENT_TYPE_DELETION_CANCELLED",
1948 Self::DeletionImmediate => "AUDIT_EVENT_TYPE_DELETION_IMMEDIATE",
1949 Self::SsoConfigured => "AUDIT_EVENT_TYPE_SSO_CONFIGURED",
1950 Self::SsoProviderCreated => "AUDIT_EVENT_TYPE_SSO_PROVIDER_CREATED",
1951 Self::SsoProviderDeleted => "AUDIT_EVENT_TYPE_SSO_PROVIDER_DELETED",
1952 Self::OrgUpdated => "AUDIT_EVENT_TYPE_ORG_UPDATED",
1953 Self::RoleCreated => "AUDIT_EVENT_TYPE_ROLE_CREATED",
1954 Self::RoleUpdated => "AUDIT_EVENT_TYPE_ROLE_UPDATED",
1955 Self::RoleDeleted => "AUDIT_EVENT_TYPE_ROLE_DELETED",
1956 Self::TemplateCreated => "AUDIT_EVENT_TYPE_TEMPLATE_CREATED",
1957 Self::TemplateUpdated => "AUDIT_EVENT_TYPE_TEMPLATE_UPDATED",
1958 Self::ApiKeyCreated => "AUDIT_EVENT_TYPE_API_KEY_CREATED",
1959 Self::ApiKeyRevoked => "AUDIT_EVENT_TYPE_API_KEY_REVOKED",
1960 Self::InviteLinkCreated => "AUDIT_EVENT_TYPE_INVITE_LINK_CREATED",
1961 Self::InviteLinkRevoked => "AUDIT_EVENT_TYPE_INVITE_LINK_REVOKED",
1962 Self::GroupCreated => "AUDIT_EVENT_TYPE_GROUP_CREATED",
1963 Self::GroupUpdated => "AUDIT_EVENT_TYPE_GROUP_UPDATED",
1964 Self::GroupDeleted => "AUDIT_EVENT_TYPE_GROUP_DELETED",
1965 Self::GroupMembersAdded => "AUDIT_EVENT_TYPE_GROUP_MEMBERS_ADDED",
1966 Self::GroupMembersRemoved => "AUDIT_EVENT_TYPE_GROUP_MEMBERS_REMOVED",
1967 Self::TeamCreated => "AUDIT_EVENT_TYPE_TEAM_CREATED",
1968 Self::TeamUpdated => "AUDIT_EVENT_TYPE_TEAM_UPDATED",
1969 Self::TeamDeleted => "AUDIT_EVENT_TYPE_TEAM_DELETED",
1970 Self::TeamMembersAdded => "AUDIT_EVENT_TYPE_TEAM_MEMBERS_ADDED",
1971 Self::TeamMembersRemoved => "AUDIT_EVENT_TYPE_TEAM_MEMBERS_REMOVED",
1972 Self::ScimUserProvisioned => "AUDIT_EVENT_TYPE_SCIM_USER_PROVISIONED",
1973 Self::ScimUserDeprovisioned => "AUDIT_EVENT_TYPE_SCIM_USER_DEPROVISIONED",
1974 Self::ScimUserUpdated => "AUDIT_EVENT_TYPE_SCIM_USER_UPDATED",
1975 Self::TranslationCreated => "AUDIT_EVENT_TYPE_TRANSLATION_CREATED",
1976 Self::TranslationApproved => "AUDIT_EVENT_TYPE_TRANSLATION_APPROVED",
1977 Self::SandboxCreated => "AUDIT_EVENT_TYPE_SANDBOX_CREATED",
1978 Self::SandboxExpired => "AUDIT_EVENT_TYPE_SANDBOX_EXPIRED",
1979 Self::AiPredictionLogged => "AUDIT_EVENT_TYPE_AI_PREDICTION_LOGGED",
1980 Self::MlPipelineTriggered => "AUDIT_EVENT_TYPE_ML_PIPELINE_TRIGGERED",
1981 Self::ArchetypeClusteringTriggered => "AUDIT_EVENT_TYPE_ARCHETYPE_CLUSTERING_TRIGGERED",
1982 Self::OrgCreated => "AUDIT_EVENT_TYPE_ORG_CREATED",
1983 Self::OrgDeleted => "AUDIT_EVENT_TYPE_ORG_DELETED",
1984 Self::ReachabilityUpsert => "AUDIT_EVENT_TYPE_REACHABILITY_UPSERT",
1985 Self::ReachabilityRemove => "AUDIT_EVENT_TYPE_REACHABILITY_REMOVE",
1986 }
1987 }
1988 /// Creates an enum from field names used in the ProtoBuf definition.
1989 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
1990 match value {
1991 "AUDIT_EVENT_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
1992 "AUDIT_EVENT_TYPE_CAMPAIGN_CREATED" => Some(Self::CampaignCreated),
1993 "AUDIT_EVENT_TYPE_MESSAGE_SENT" => Some(Self::MessageSent),
1994 "AUDIT_EVENT_TYPE_MESSAGE_OPENED" => Some(Self::MessageOpened),
1995 "AUDIT_EVENT_TYPE_ACK_REGISTERED" => Some(Self::AckRegistered),
1996 "AUDIT_EVENT_TYPE_ESCALATION_EXECUTED" => Some(Self::EscalationExecuted),
1997 "AUDIT_EVENT_TYPE_CAMPAIGN_STARTED" => Some(Self::CampaignStarted),
1998 "AUDIT_EVENT_TYPE_CAMPAIGN_CANCELLED" => Some(Self::CampaignCancelled),
1999 "AUDIT_EVENT_TYPE_CAMPAIGN_UPDATED" => Some(Self::CampaignUpdated),
2000 "AUDIT_EVENT_TYPE_USER_INVITED" => Some(Self::UserInvited),
2001 "AUDIT_EVENT_TYPE_USER_DEACTIVATED" => Some(Self::UserDeactivated),
2002 "AUDIT_EVENT_TYPE_USER_REACTIVATED" => Some(Self::UserReactivated),
2003 "AUDIT_EVENT_TYPE_ROLE_CHANGED" => Some(Self::RoleChanged),
2004 "AUDIT_EVENT_TYPE_INVITE_REVOKED" => Some(Self::InviteRevoked),
2005 "AUDIT_EVENT_TYPE_PROFILE_UPDATED" => Some(Self::ProfileUpdated),
2006 "AUDIT_EVENT_TYPE_SETTINGS_UPDATED" => Some(Self::SettingsUpdated),
2007 "AUDIT_EVENT_TYPE_PASSKEY_ENROLLED" => Some(Self::PasskeyEnrolled),
2008 "AUDIT_EVENT_TYPE_DATA_EXPORT_REQUESTED" => Some(Self::DataExportRequested),
2009 "AUDIT_EVENT_TYPE_DATA_DELETION_REQUESTED" => Some(Self::DataDeletionRequested),
2010 "AUDIT_EVENT_TYPE_DATA_RECTIFIED" => Some(Self::DataRectified),
2011 "AUDIT_EVENT_TYPE_PROCESSING_RESTRICTED" => Some(Self::ProcessingRestricted),
2012 "AUDIT_EVENT_TYPE_DELETION_CANCELLED" => Some(Self::DeletionCancelled),
2013 "AUDIT_EVENT_TYPE_DELETION_IMMEDIATE" => Some(Self::DeletionImmediate),
2014 "AUDIT_EVENT_TYPE_SSO_CONFIGURED" => Some(Self::SsoConfigured),
2015 "AUDIT_EVENT_TYPE_SSO_PROVIDER_CREATED" => Some(Self::SsoProviderCreated),
2016 "AUDIT_EVENT_TYPE_SSO_PROVIDER_DELETED" => Some(Self::SsoProviderDeleted),
2017 "AUDIT_EVENT_TYPE_ORG_UPDATED" => Some(Self::OrgUpdated),
2018 "AUDIT_EVENT_TYPE_ROLE_CREATED" => Some(Self::RoleCreated),
2019 "AUDIT_EVENT_TYPE_ROLE_UPDATED" => Some(Self::RoleUpdated),
2020 "AUDIT_EVENT_TYPE_ROLE_DELETED" => Some(Self::RoleDeleted),
2021 "AUDIT_EVENT_TYPE_TEMPLATE_CREATED" => Some(Self::TemplateCreated),
2022 "AUDIT_EVENT_TYPE_TEMPLATE_UPDATED" => Some(Self::TemplateUpdated),
2023 "AUDIT_EVENT_TYPE_API_KEY_CREATED" => Some(Self::ApiKeyCreated),
2024 "AUDIT_EVENT_TYPE_API_KEY_REVOKED" => Some(Self::ApiKeyRevoked),
2025 "AUDIT_EVENT_TYPE_INVITE_LINK_CREATED" => Some(Self::InviteLinkCreated),
2026 "AUDIT_EVENT_TYPE_INVITE_LINK_REVOKED" => Some(Self::InviteLinkRevoked),
2027 "AUDIT_EVENT_TYPE_GROUP_CREATED" => Some(Self::GroupCreated),
2028 "AUDIT_EVENT_TYPE_GROUP_UPDATED" => Some(Self::GroupUpdated),
2029 "AUDIT_EVENT_TYPE_GROUP_DELETED" => Some(Self::GroupDeleted),
2030 "AUDIT_EVENT_TYPE_GROUP_MEMBERS_ADDED" => Some(Self::GroupMembersAdded),
2031 "AUDIT_EVENT_TYPE_GROUP_MEMBERS_REMOVED" => Some(Self::GroupMembersRemoved),
2032 "AUDIT_EVENT_TYPE_TEAM_CREATED" => Some(Self::TeamCreated),
2033 "AUDIT_EVENT_TYPE_TEAM_UPDATED" => Some(Self::TeamUpdated),
2034 "AUDIT_EVENT_TYPE_TEAM_DELETED" => Some(Self::TeamDeleted),
2035 "AUDIT_EVENT_TYPE_TEAM_MEMBERS_ADDED" => Some(Self::TeamMembersAdded),
2036 "AUDIT_EVENT_TYPE_TEAM_MEMBERS_REMOVED" => Some(Self::TeamMembersRemoved),
2037 "AUDIT_EVENT_TYPE_SCIM_USER_PROVISIONED" => Some(Self::ScimUserProvisioned),
2038 "AUDIT_EVENT_TYPE_SCIM_USER_DEPROVISIONED" => Some(Self::ScimUserDeprovisioned),
2039 "AUDIT_EVENT_TYPE_SCIM_USER_UPDATED" => Some(Self::ScimUserUpdated),
2040 "AUDIT_EVENT_TYPE_TRANSLATION_CREATED" => Some(Self::TranslationCreated),
2041 "AUDIT_EVENT_TYPE_TRANSLATION_APPROVED" => Some(Self::TranslationApproved),
2042 "AUDIT_EVENT_TYPE_SANDBOX_CREATED" => Some(Self::SandboxCreated),
2043 "AUDIT_EVENT_TYPE_SANDBOX_EXPIRED" => Some(Self::SandboxExpired),
2044 "AUDIT_EVENT_TYPE_AI_PREDICTION_LOGGED" => Some(Self::AiPredictionLogged),
2045 "AUDIT_EVENT_TYPE_ML_PIPELINE_TRIGGERED" => Some(Self::MlPipelineTriggered),
2046 "AUDIT_EVENT_TYPE_ARCHETYPE_CLUSTERING_TRIGGERED" => Some(Self::ArchetypeClusteringTriggered),
2047 "AUDIT_EVENT_TYPE_ORG_CREATED" => Some(Self::OrgCreated),
2048 "AUDIT_EVENT_TYPE_ORG_DELETED" => Some(Self::OrgDeleted),
2049 "AUDIT_EVENT_TYPE_REACHABILITY_UPSERT" => Some(Self::ReachabilityUpsert),
2050 "AUDIT_EVENT_TYPE_REACHABILITY_REMOVE" => Some(Self::ReachabilityRemove),
2051 _ => None,
2052 }
2053 }
2054}
2055/// Format for audit trail export.
2056#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2057#[repr(i32)]
2058pub enum AuditExportFormat {
2059 /// Default value; should not be used explicitly.
2060 Unspecified = 0,
2061 /// Comma-separated values.
2062 Csv = 1,
2063 /// JSON lines format.
2064 Json = 2,
2065 /// Apache Parquet columnar format.
2066 Parquet = 3,
2067}
2068impl AuditExportFormat {
2069 /// String value of the enum field names used in the ProtoBuf definition.
2070 ///
2071 /// The values are not transformed in any way and thus are considered stable
2072 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
2073 pub fn as_str_name(&self) -> &'static str {
2074 match self {
2075 Self::Unspecified => "AUDIT_EXPORT_FORMAT_UNSPECIFIED",
2076 Self::Csv => "AUDIT_EXPORT_FORMAT_CSV",
2077 Self::Json => "AUDIT_EXPORT_FORMAT_JSON",
2078 Self::Parquet => "AUDIT_EXPORT_FORMAT_PARQUET",
2079 }
2080 }
2081 /// Creates an enum from field names used in the ProtoBuf definition.
2082 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
2083 match value {
2084 "AUDIT_EXPORT_FORMAT_UNSPECIFIED" => Some(Self::Unspecified),
2085 "AUDIT_EXPORT_FORMAT_CSV" => Some(Self::Csv),
2086 "AUDIT_EXPORT_FORMAT_JSON" => Some(Self::Json),
2087 "AUDIT_EXPORT_FORMAT_PARQUET" => Some(Self::Parquet),
2088 _ => None,
2089 }
2090 }
2091}
2092// ─── Messages ─────────────────────────────────────────────────────────────────
2093
2094/// Request to resolve the effective permission set for one principal.
2095#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2096pub struct ResolvePrincipalPermissionsRequest {
2097 /// UUID of the subject whose permissions are being resolved (user or
2098 /// principal identifier).
2099 #[prost(string, tag="1")]
2100 pub subject: ::prost::alloc::string::String,
2101 /// Organization the resolution is scoped to.
2102 #[prost(string, tag="2")]
2103 pub org_id: ::prost::alloc::string::String,
2104 /// Kind of principal identified by `subject`.
2105 #[prost(enumeration="PrincipalType", tag="3")]
2106 pub principal_type: i32,
2107}
2108/// Effective permissions resolved for the requested principal.
2109#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2110pub struct ResolvePrincipalPermissionsResponse {
2111 /// Flattened, deduplicated set of permissions granted to the principal in
2112 /// the requested organization. Empty when the principal has no grants.
2113 #[prost(enumeration="Permission", repeated, tag="1")]
2114 pub permissions: ::prost::alloc::vec::Vec<i32>,
2115}
2116// ─── Enums ──────────────────────────────────────────────────────────────────
2117
2118/// Kind of principal whose permissions are being resolved.
2119#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2120#[repr(i32)]
2121pub enum PrincipalType {
2122 Unspecified = 0,
2123 /// An end user identified by their user UUID, scoped to one organization.
2124 User = 1,
2125 /// An organization acting as its own principal (e.g. a service identity
2126 /// operating on behalf of the whole org rather than a member).
2127 Org = 2,
2128 /// A platform staff principal whose permissions derive from a role within
2129 /// the ORG_TYPE_STAFF organization.
2130 Staff = 3,
2131}
2132impl PrincipalType {
2133 /// String value of the enum field names used in the ProtoBuf definition.
2134 ///
2135 /// The values are not transformed in any way and thus are considered stable
2136 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
2137 pub fn as_str_name(&self) -> &'static str {
2138 match self {
2139 Self::Unspecified => "PRINCIPAL_TYPE_UNSPECIFIED",
2140 Self::User => "PRINCIPAL_TYPE_USER",
2141 Self::Org => "PRINCIPAL_TYPE_ORG",
2142 Self::Staff => "PRINCIPAL_TYPE_STAFF",
2143 }
2144 }
2145 /// Creates an enum from field names used in the ProtoBuf definition.
2146 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
2147 match value {
2148 "PRINCIPAL_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
2149 "PRINCIPAL_TYPE_USER" => Some(Self::User),
2150 "PRINCIPAL_TYPE_ORG" => Some(Self::Org),
2151 "PRINCIPAL_TYPE_STAFF" => Some(Self::Staff),
2152 _ => None,
2153 }
2154 }
2155}
2156// ─── Messages ───────────────────────────────────────────────────────────────
2157
2158/// A campaign that delivers structured messages to a set of recipients
2159/// and tracks their engagement through a workflow.
2160#[derive(Clone, PartialEq, ::prost::Message)]
2161pub struct Campaign {
2162 /// Unique identifier for the campaign.
2163 /// Constraints: UUID format (36 characters).
2164 #[prost(string, tag="1")]
2165 pub id: ::prost::alloc::string::String,
2166 /// Human-readable campaign name.
2167 /// Constraints: Max length 200 characters.
2168 #[prost(string, tag="2")]
2169 pub name: ::prost::alloc::string::String,
2170 /// ID of the template used to render messages.
2171 /// Constraints: UUID format (36 characters).
2172 #[prost(string, tag="3")]
2173 pub template_id: ::prost::alloc::string::String,
2174 /// Pinned version of the template used for this campaign.
2175 #[prost(int32, tag="4")]
2176 pub template_version: i32,
2177 /// Object storage reference to the audience snapshot taken at campaign creation.
2178 #[prost(string, tag="5")]
2179 pub audience_snapshot_ref: ::prost::alloc::string::String,
2180 /// Current lifecycle status of the campaign.
2181 #[prost(enumeration="CampaignStatus", tag="6")]
2182 pub status: i32,
2183 /// Workflow DAG that drives the campaign's automation logic.
2184 #[prost(message, optional, tag="7")]
2185 pub workflow: ::core::option::Option<WorkflowDefinition>,
2186 /// Total number of recipients in the audience snapshot.
2187 #[prost(int32, tag="8")]
2188 pub total_recipients: i32,
2189 /// Number of recipients who completed the required action.
2190 #[prost(int32, tag="9")]
2191 pub action_completed_count: i32,
2192 /// Number of recipients who did not act before the deadline.
2193 #[prost(int32, tag="10")]
2194 pub missed_count: i32,
2195 /// Timestamp when the campaign was created.
2196 #[prost(message, optional, tag="11")]
2197 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
2198 /// Timestamp when the campaign was started (workflow execution began).
2199 #[prost(message, optional, tag="12")]
2200 pub started_at: ::core::option::Option<::prost_types::Timestamp>,
2201 /// Timestamp when the campaign finished (completed, failed, or cancelled).
2202 #[prost(message, optional, tag="13")]
2203 pub completed_at: ::core::option::Option<::prost_types::Timestamp>,
2204 /// Display name of the sender shown to recipients (e.g. "HR Team").
2205 /// Constraints: Max length 200 characters.
2206 #[prost(string, tag="14")]
2207 pub sender_name: ::prost::alloc::string::String,
2208 /// Optional user-facing title override. If set, takes precedence over the template title.
2209 /// Constraints: Max length 200 characters.
2210 #[prost(string, tag="15")]
2211 pub title: ::prost::alloc::string::String,
2212 /// Whether this campaign's notifications break through Do Not Disturb / Focus mode.
2213 #[prost(bool, tag="16")]
2214 pub critical: bool,
2215 /// Optional locale override for all recipients in this campaign.
2216 /// When set, all recipients receive the campaign in this locale regardless of
2217 /// their preferred_locale. Empty means per-recipient locale resolution.
2218 /// Valid values: en, es, pt-BR, zh, ja.
2219 #[prost(string, tag="17")]
2220 pub default_locale: ::prost::alloc::string::String,
2221 /// Whether the campaign deadline waits for users without registered devices.
2222 /// When true, NO_DEVICE users remain in pending_count and can acknowledge
2223 /// via inbox after installing the app. Default false preserves current behavior.
2224 #[prost(bool, tag="18")]
2225 pub wait_for_enrollment: bool,
2226 /// Optional. Set when the campaign was created from a Compass archetype CTA.
2227 /// Drives post-campaign archetype-response analytics.
2228 #[prost(message, optional, tag="19")]
2229 pub originating_archetype: ::core::option::Option<CampaignOriginatingArchetype>,
2230 /// True when this campaign contains synthetic (artificially injected) data —
2231 /// created or populated for demos, sandbox testing, or issue reproduction.
2232 #[prost(bool, tag="20")]
2233 pub synthetic: bool,
2234 /// Number of recipients frozen in the audience snapshot at creation time.
2235 /// Unlike total_recipients (which counts deliveries and is 0 until the
2236 /// campaign starts), this is known as soon as the campaign exists.
2237 /// 0 when the campaign predates snapshot-size tracking.
2238 #[prost(int32, tag="21")]
2239 pub audience_snapshot_size: i32,
2240 /// Number of members currently eligible for this campaign's audience,
2241 /// computed at read time. Compare with audience_snapshot_size to see how far
2242 /// the frozen audience has drifted from the present membership.
2243 #[prost(int32, tag="22")]
2244 pub current_audience_size: i32,
2245 /// True when the frozen audience no longer covers the current eligible
2246 /// membership (current_audience_size > audience_snapshot_size). Clients
2247 /// should surface this before the campaign is started: recipients added
2248 /// after creation are NOT reached unless the campaign is recreated.
2249 #[prost(bool, tag="23")]
2250 pub audience_snapshot_stale: bool,
2251}
2252/// Identifies the archetype that motivated the creation of a campaign.
2253/// The audience is NOT filtered by archetype membership — this is metadata
2254/// about the campaign's authoring intent only. See OpenSpec change
2255/// archetype-targeted-campaign-cta.
2256#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2257pub struct CampaignOriginatingArchetype {
2258 /// UUID of the group whose archetype set the label belongs to.
2259 #[prost(string, tag="1")]
2260 pub group_id: ::prost::alloc::string::String,
2261 /// Stable archetype label (e.g., "Swift Acknowledger"). Labels are stable
2262 /// across clustering retrains; archetype IDs are not.
2263 #[prost(string, tag="2")]
2264 pub archetype_label: ::prost::alloc::string::String,
2265}
2266/// A single audience member with optional per-user template variables.
2267#[derive(Clone, PartialEq, ::prost::Message)]
2268pub struct AudienceMember {
2269 /// User ID (UUID).
2270 #[prost(string, tag="1")]
2271 pub user_id: ::prost::alloc::string::String,
2272 /// Template variable values for this user (e.g. {"name": "Alice"}).
2273 #[prost(map="string, string", tag="2")]
2274 pub variables: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
2275}
2276/// Request to create a new campaign.
2277#[derive(Clone, PartialEq, ::prost::Message)]
2278pub struct CreateCampaignRequest {
2279 /// Human-readable campaign name (admin-facing label).
2280 /// Constraints: Max length 200 characters.
2281 #[prost(string, tag="1")]
2282 pub name: ::prost::alloc::string::String,
2283 /// ID of the template to use for rendering messages.
2284 /// Constraints: UUID format (36 characters).
2285 #[prost(string, tag="2")]
2286 pub template_id: ::prost::alloc::string::String,
2287 /// Version of the template to pin for this campaign.
2288 #[prost(int32, tag="3")]
2289 pub template_version: i32,
2290 /// List of user IDs that form the campaign audience.
2291 /// Constraints: Max 100000 items.
2292 #[prost(string, repeated, tag="4")]
2293 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
2294 /// Workflow DAG defining the campaign's automation steps.
2295 /// Required: CreateCampaign rejects a request with no workflow
2296 /// (INVALID_ARGUMENT) and does not substitute a default. The definition
2297 /// MUST validate as an acyclic graph of well-formed steps.
2298 #[prost(message, optional, tag="5")]
2299 pub workflow: ::core::option::Option<WorkflowDefinition>,
2300 /// Display name of the sender shown to recipients (e.g. "HR Team").
2301 /// Constraints: Max length 200 characters.
2302 #[prost(string, tag="6")]
2303 pub sender_name: ::prost::alloc::string::String,
2304 /// Optional user-facing title override. If empty, the template title is used.
2305 /// Constraints: Max length 200 characters.
2306 #[prost(string, tag="7")]
2307 pub title: ::prost::alloc::string::String,
2308 /// Rich audience with per-user template variables.
2309 /// When set, takes precedence over user_ids.
2310 /// Constraints: Max 100000 items.
2311 #[prost(message, repeated, tag="8")]
2312 pub audience: ::prost::alloc::vec::Vec<AudienceMember>,
2313 /// Whether to include users with processing_restricted=true in the audience.
2314 /// Default false: restricted users are excluded. Set true only with Art. 18(2) legal basis.
2315 #[prost(bool, tag="9")]
2316 pub include_restricted: bool,
2317 /// Whether this campaign's notifications break through Do Not Disturb / Focus mode.
2318 #[prost(bool, tag="10")]
2319 pub critical: bool,
2320 /// Optional locale override for all recipients.
2321 #[prost(string, tag="11")]
2322 pub default_locale: ::prost::alloc::string::String,
2323 /// Whether the campaign deadline should wait for users without registered devices.
2324 /// When true, NO_DEVICE users are not decremented from pending_count,
2325 /// allowing them to acknowledge via inbox after installing the app.
2326 #[prost(bool, tag="12")]
2327 pub wait_for_enrollment: bool,
2328 /// Optional. Set when the campaign is created from a Compass archetype CTA.
2329 /// The server validates the caller has access to group_id and that
2330 /// archetype_label exists in the group's current archetype set; cross-org
2331 /// group_id returns PERMISSION_DENIED, unknown label returns NOT_FOUND.
2332 #[prost(message, optional, tag="13")]
2333 pub originating_archetype: ::core::option::Option<CampaignOriginatingArchetype>,
2334}
2335/// Response after creating a campaign.
2336#[derive(Clone, PartialEq, ::prost::Message)]
2337pub struct CreateCampaignResponse {
2338 /// The newly created campaign.
2339 #[prost(message, optional, tag="1")]
2340 pub campaign: ::core::option::Option<Campaign>,
2341}
2342/// Request to start a campaign's workflow execution.
2343#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2344pub struct StartCampaignRequest {
2345 /// ID of the campaign to start.
2346 /// Constraints: UUID format (36 characters).
2347 #[prost(string, tag="1")]
2348 pub campaign_id: ::prost::alloc::string::String,
2349}
2350/// Response after starting a campaign.
2351#[derive(Clone, PartialEq, ::prost::Message)]
2352pub struct StartCampaignResponse {
2353 /// The campaign with updated status.
2354 #[prost(message, optional, tag="1")]
2355 pub campaign: ::core::option::Option<Campaign>,
2356}
2357/// Request to retrieve a single campaign by ID.
2358#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2359pub struct GetCampaignRequest {
2360 /// ID of the campaign to retrieve.
2361 /// Constraints: UUID format (36 characters).
2362 #[prost(string, tag="1")]
2363 pub campaign_id: ::prost::alloc::string::String,
2364}
2365/// Response containing the requested campaign.
2366#[derive(Clone, PartialEq, ::prost::Message)]
2367pub struct GetCampaignResponse {
2368 /// The requested campaign.
2369 #[prost(message, optional, tag="1")]
2370 pub campaign: ::core::option::Option<Campaign>,
2371}
2372/// Request to list campaigns with pagination.
2373#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2374pub struct ListCampaignsRequest {
2375 /// Pagination parameters.
2376 #[prost(message, optional, tag="1")]
2377 pub pagination: ::core::option::Option<Pagination>,
2378}
2379/// Response containing a page of campaigns.
2380#[derive(Clone, PartialEq, ::prost::Message)]
2381pub struct ListCampaignsResponse {
2382 /// List of campaigns in this page.
2383 #[prost(message, repeated, tag="1")]
2384 pub campaigns: ::prost::alloc::vec::Vec<Campaign>,
2385 /// Pagination metadata for fetching subsequent pages.
2386 #[prost(message, optional, tag="2")]
2387 pub pagination_meta: ::core::option::Option<PaginationMeta>,
2388}
2389/// Request to cancel a running campaign.
2390#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2391pub struct CancelCampaignRequest {
2392 /// ID of the campaign to cancel.
2393 /// Constraints: UUID format (36 characters).
2394 #[prost(string, tag="1")]
2395 pub campaign_id: ::prost::alloc::string::String,
2396}
2397/// Response after cancelling a campaign.
2398#[derive(Clone, PartialEq, ::prost::Message)]
2399pub struct CancelCampaignResponse {
2400 /// The campaign with updated status (CANCELLED).
2401 #[prost(message, optional, tag="1")]
2402 pub campaign: ::core::option::Option<Campaign>,
2403}
2404/// Request to update a draft campaign (status must be CREATED).
2405/// Only non-empty/non-zero fields are updated; omitted fields remain unchanged.
2406#[derive(Clone, PartialEq, ::prost::Message)]
2407pub struct UpdateCampaignRequest {
2408 /// ID of the campaign to update.
2409 /// Constraints: UUID format (36 characters).
2410 #[prost(string, tag="1")]
2411 pub campaign_id: ::prost::alloc::string::String,
2412 /// Updated campaign name. Empty string means no change.
2413 /// Constraints: Max length 200 characters.
2414 #[prost(string, tag="2")]
2415 pub name: ::prost::alloc::string::String,
2416 /// Updated sender display name. Empty string means no change.
2417 /// Constraints: Max length 200 characters.
2418 #[prost(string, tag="3")]
2419 pub sender_name: ::prost::alloc::string::String,
2420 /// Updated title override. Empty string means no change.
2421 /// Constraints: Max length 200 characters.
2422 #[prost(string, tag="4")]
2423 pub title: ::prost::alloc::string::String,
2424 /// Updated template ID. Empty string means no change.
2425 /// Constraints: UUID format (36 characters).
2426 #[prost(string, tag="5")]
2427 pub template_id: ::prost::alloc::string::String,
2428 /// Updated template version. Zero means no change.
2429 #[prost(int32, tag="6")]
2430 pub template_version: i32,
2431 /// Updated workflow DAG. Null/omitted means no change.
2432 #[prost(message, optional, tag="7")]
2433 pub workflow: ::core::option::Option<WorkflowDefinition>,
2434 /// Replaces the campaign's frozen audience snapshot. Omitted means no
2435 /// change; PRESENT means replace — including with an empty member list
2436 /// (a campaign with no recipients is a valid state). The wrapper message
2437 /// exists exactly for that presence distinction, which a bare repeated
2438 /// field cannot express. Only valid while the campaign is in CREATED
2439 /// status; the server rejects the replacement once the campaign has
2440 /// started, since deliveries were already created from the old snapshot.
2441 #[prost(message, optional, tag="8")]
2442 pub audience_replacement: ::core::option::Option<AudienceReplacement>,
2443}
2444/// A full replacement for a campaign's frozen audience. Presence of this
2445/// message (not its member count) signals the replace intent.
2446#[derive(Clone, PartialEq, ::prost::Message)]
2447pub struct AudienceReplacement {
2448 /// The new complete audience. Replaces the previous snapshot wholesale.
2449 #[prost(message, repeated, tag="1")]
2450 pub members: ::prost::alloc::vec::Vec<AudienceMember>,
2451}
2452/// Response after updating a campaign.
2453#[derive(Clone, PartialEq, ::prost::Message)]
2454pub struct UpdateCampaignResponse {
2455 /// The campaign with updated fields.
2456 #[prost(message, optional, tag="1")]
2457 pub campaign: ::core::option::Option<Campaign>,
2458}
2459/// Request to read a campaign's frozen audience snapshot.
2460#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2461pub struct GetCampaignAudienceRequest {
2462 /// ID of the campaign whose audience to read.
2463 /// Constraints: UUID format (36 characters).
2464 #[prost(string, tag="1")]
2465 pub campaign_id: ::prost::alloc::string::String,
2466}
2467/// One member of a campaign's frozen audience, enriched with the identity
2468/// fields a client needs to render the member without further lookups.
2469#[derive(Clone, PartialEq, ::prost::Message)]
2470pub struct CampaignAudienceEntry {
2471 /// The frozen audience row exactly as it will be delivered to: user id
2472 /// plus per-user template variables.
2473 #[prost(message, optional, tag="1")]
2474 pub member: ::core::option::Option<AudienceMember>,
2475 /// The member's email at read time. Empty when the user no longer
2476 /// resolves (deactivated or erased since the audience was frozen).
2477 #[prost(string, tag="2")]
2478 pub email: ::prost::alloc::string::String,
2479 /// The member's display name at read time. Empty when unresolvable.
2480 #[prost(string, tag="3")]
2481 pub display_name: ::prost::alloc::string::String,
2482 /// False when the user is no longer an active or invited member of the
2483 /// organization — a frozen recipient that would not be reachable today.
2484 #[prost(bool, tag="4")]
2485 pub active: bool,
2486}
2487/// A campaign's frozen audience. Empty when the campaign has no audience
2488/// snapshot (legacy campaigns predating snapshot tracking) or the snapshot
2489/// is empty.
2490#[derive(Clone, PartialEq, ::prost::Message)]
2491pub struct GetCampaignAudienceResponse {
2492 /// The frozen audience, enriched per entry.
2493 #[prost(message, repeated, tag="1")]
2494 pub entries: ::prost::alloc::vec::Vec<CampaignAudienceEntry>,
2495}
2496/// A single delivery record tracking message delivery to one recipient.
2497/// Out-of-band context attached to a delivery beyond its canonical
2498/// recipient + status + content payload. Optional; fields are populated
2499/// per delivery kind. Currently only REMINDER_FYI children carry values,
2500/// to snapshot context from the parent delivery so clients can render
2501/// without fetching additional resources.
2502#[derive(Clone, PartialEq, ::prost::Message)]
2503pub struct DeliveryMetadata {
2504 /// REMINDER_FYI: the rendered Message payload from the parent delivery,
2505 /// used to render the blockquoted "Original message" panel on the
2506 /// notify-target's inbox card.
2507 #[prost(message, optional, tag="1")]
2508 pub original_message: ::core::option::Option<Message>,
2509 /// REMINDER_FYI: display name of the original recipient (the employee
2510 /// who hasn't responded). Used to interpolate the FYI title and banner.
2511 #[prost(string, tag="2")]
2512 pub original_recipient_name: ::prost::alloc::string::String,
2513 /// REMINDER_FYI: campaign title, denormalized so the notify-target's
2514 /// client can render without a separate campaign lookup.
2515 #[prost(string, tag="3")]
2516 pub campaign_title: ::prost::alloc::string::String,
2517 /// REMINDER_FYI: when the parent reminder step fired, used to render
2518 /// the "fired X ago" footer on the FYI card.
2519 #[prost(message, optional, tag="4")]
2520 pub reminder_fired_at: ::core::option::Option<::prost_types::Timestamp>,
2521}
2522#[derive(Clone, PartialEq, ::prost::Message)]
2523pub struct Delivery {
2524 /// Unique identifier for this delivery.
2525 /// Constraints: UUID format (36 characters).
2526 #[prost(string, tag="1")]
2527 pub id: ::prost::alloc::string::String,
2528 /// ID of the recipient user.
2529 /// Constraints: UUID format (36 characters).
2530 #[prost(string, tag="2")]
2531 pub user_id: ::prost::alloc::string::String,
2532 /// ID of the campaign this delivery belongs to.
2533 /// Constraints: UUID format (36 characters).
2534 #[prost(string, tag="3")]
2535 pub campaign_id: ::prost::alloc::string::String,
2536 /// Current delivery status.
2537 #[prost(enumeration="DeliveryStatus", tag="4")]
2538 pub status: i32,
2539 /// Timestamp when the message was delivered to the device.
2540 #[prost(message, optional, tag="5")]
2541 pub delivered_at: ::core::option::Option<::prost_types::Timestamp>,
2542 /// Timestamp when the recipient read the message.
2543 #[prost(message, optional, tag="6")]
2544 pub read_at: ::core::option::Option<::prost_types::Timestamp>,
2545 /// Timestamp when the recipient performed the required action.
2546 #[prost(message, optional, tag="7")]
2547 pub acted_at: ::core::option::Option<::prost_types::Timestamp>,
2548 /// Email address of the recipient, populated from the users table on read.
2549 #[prost(string, tag="8")]
2550 pub recipient_email: ::prost::alloc::string::String,
2551 /// Discriminator distinguishing primary recipient deliveries from
2552 /// deliveries generated by downstream workflow steps.
2553 #[prost(enumeration="delivery::Kind", tag="12")]
2554 pub kind: i32,
2555 /// For non-primary deliveries, the UUID of the originating delivery this
2556 /// row was derived from. Empty for primary deliveries.
2557 /// Constraints: UUID format (36 characters) when set.
2558 #[prost(string, tag="13")]
2559 pub parent_delivery_id: ::prost::alloc::string::String,
2560 /// The locale this delivery's body was actually rendered in after fallback
2561 /// resolution (recipient preference, campaign override, template default).
2562 /// Valid values: en, es, pt-BR, zh, ja.
2563 #[prost(string, tag="14")]
2564 pub rendered_locale: ::prost::alloc::string::String,
2565 /// Optional out-of-band context. See `DeliveryMetadata` for which
2566 /// delivery kinds populate which fields. Empty for legacy / PRIMARY
2567 /// deliveries.
2568 #[prost(message, optional, tag="15")]
2569 pub metadata: ::core::option::Option<DeliveryMetadata>,
2570 /// True when this delivery's outcome is synthetic (artificially injected)
2571 /// data rather than the result of a real delivery and user response.
2572 #[prost(bool, tag="9")]
2573 pub synthetic: bool,
2574}
2575/// Nested message and enum types in `Delivery`.
2576pub mod delivery {
2577 /// Discriminator describing what produced this delivery row.
2578 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2579 #[repr(i32)]
2580 pub enum Kind {
2581 /// Default value; not a valid kind.
2582 Unspecified = 0,
2583 /// Delivery generated for an audience recipient at campaign start.
2584 Primary = 1,
2585 /// Delivery generated by an escalation step targeting a non-audience user.
2586 Escalation = 2,
2587 /// Passive heads-up delivery generated when a reminder step fans out to
2588 /// its `notify_targets`. Carries no action button; auto-dismisses when
2589 /// the parent delivery is acknowledged. See
2590 /// `SendReminderConfig.notify_targets`.
2591 ReminderFyi = 3,
2592 }
2593 impl Kind {
2594 /// String value of the enum field names used in the ProtoBuf definition.
2595 ///
2596 /// The values are not transformed in any way and thus are considered stable
2597 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
2598 pub fn as_str_name(&self) -> &'static str {
2599 match self {
2600 Self::Unspecified => "KIND_UNSPECIFIED",
2601 Self::Primary => "KIND_PRIMARY",
2602 Self::Escalation => "KIND_ESCALATION",
2603 Self::ReminderFyi => "KIND_REMINDER_FYI",
2604 }
2605 }
2606 /// Creates an enum from field names used in the ProtoBuf definition.
2607 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
2608 match value {
2609 "KIND_UNSPECIFIED" => Some(Self::Unspecified),
2610 "KIND_PRIMARY" => Some(Self::Primary),
2611 "KIND_ESCALATION" => Some(Self::Escalation),
2612 "KIND_REMINDER_FYI" => Some(Self::ReminderFyi),
2613 _ => None,
2614 }
2615 }
2616 }
2617}
2618/// Request to list deliveries for a campaign with optional status filtering.
2619#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2620pub struct ListDeliveriesRequest {
2621 /// ID of the campaign to list deliveries for.
2622 /// Constraints: UUID format (36 characters).
2623 #[prost(string, tag="1")]
2624 pub campaign_id: ::prost::alloc::string::String,
2625 /// Optional filter by delivery status. UNSPECIFIED returns all.
2626 #[prost(enumeration="DeliveryStatus", tag="2")]
2627 pub status_filter: i32,
2628 /// Pagination parameters.
2629 #[prost(message, optional, tag="3")]
2630 pub pagination: ::core::option::Option<Pagination>,
2631}
2632/// Response containing a page of delivery records.
2633#[derive(Clone, PartialEq, ::prost::Message)]
2634pub struct ListDeliveriesResponse {
2635 /// List of deliveries in this page.
2636 #[prost(message, repeated, tag="1")]
2637 pub deliveries: ::prost::alloc::vec::Vec<Delivery>,
2638 /// Pagination metadata for fetching subsequent pages.
2639 #[prost(message, optional, tag="2")]
2640 pub pagination_meta: ::core::option::Option<PaginationMeta>,
2641}
2642/// Request to compute the archetype-tendency-shift surface for a campaign:
2643/// how each archetype's share of the originating group has moved between
2644/// the snapshot closest to campaign-creation time and the most recent
2645/// snapshot. Only valid for campaigns whose originating_archetype is set.
2646#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2647pub struct GetCampaignArchetypeBreakdownRequest {
2648 /// ID of the campaign to break down.
2649 /// Constraints: UUID format (36 characters).
2650 #[prost(string, tag="1")]
2651 pub campaign_id: ::prost::alloc::string::String,
2652}
2653/// Movement in one archetype's share of the originating group between the
2654/// "before" and "after" archetype-clustering snapshots. Cohort-level only;
2655/// no joining to user identity. The `is_origin` row is the archetype the
2656/// campaign was authored for.
2657#[derive(Clone, PartialEq, ::prost::Message)]
2658pub struct ArchetypeShareShift {
2659 /// Stable archetype label, e.g. "Swift Acknowledger".
2660 #[prost(string, tag="1")]
2661 pub label: ::prost::alloc::string::String,
2662 /// Archetype's share of the group at the snapshot closest to (but not
2663 /// after) the campaign's created_at. Range 0.0 – 1.0.
2664 #[prost(double, tag="2")]
2665 pub share_before: f64,
2666 /// Archetype's share of the group at the most recent snapshot. Range
2667 /// 0.0 – 1.0. Equals share_before when no clustering has run since.
2668 #[prost(double, tag="3")]
2669 pub share_after: f64,
2670 /// True when this row's label matches the campaign's
2671 /// originating_archetype.archetype_label.
2672 #[prost(bool, tag="4")]
2673 pub is_origin: bool,
2674 /// Count of email DELIVERED events recorded for this archetype's members
2675 /// across the campaign window. Denominator for both open-rate fields.
2676 #[prost(uint64, tag="5")]
2677 pub email_delivered_count: u64,
2678 /// Open rate excluding events flagged as Apple-MPP prefetches
2679 /// (prefetch_suspected=true). Range 0.0 – 1.0.
2680 #[prost(double, tag="6")]
2681 pub email_open_rate_real: f64,
2682 /// Open rate including all OPENED events, prefetches included.
2683 /// Range 0.0 – 1.0.
2684 #[prost(double, tag="7")]
2685 pub email_open_rate_raw: f64,
2686}
2687/// Response containing per-archetype share shifts. The admin renders
2688/// these as a comparison table — origin row marked, others as peers, so
2689/// the admin can tell campaign-coincident drift apart from background
2690/// drift across the rest of the group.
2691#[derive(Clone, PartialEq, ::prost::Message)]
2692pub struct GetCampaignArchetypeBreakdownResponse {
2693 /// One entry per archetype in the originating group. Empty when
2694 /// insufficient_history is true.
2695 #[prost(message, repeated, tag="1")]
2696 pub shifts: ::prost::alloc::vec::Vec<ArchetypeShareShift>,
2697 /// When the "before" sample was taken (closest snapshot at or before
2698 /// campaign creation).
2699 #[prost(message, optional, tag="2")]
2700 pub before_snapshot_at: ::core::option::Option<::prost_types::Timestamp>,
2701 /// When the "after" sample was taken (most recent snapshot).
2702 #[prost(message, optional, tag="3")]
2703 pub after_snapshot_at: ::core::option::Option<::prost_types::Timestamp>,
2704 /// True when fewer than two clustering snapshots exist for the group,
2705 /// so no shift can be computed yet. Admin renders an "awaiting next
2706 /// clustering cycle" empty state.
2707 #[prost(bool, tag="4")]
2708 pub insufficient_history: bool,
2709}
2710// ─── Short-code messages ────────────────────────────────────────────────────
2711
2712/// Request to resolve a campaign's short-code, lazily generating one on
2713/// first call. Used by internal-service callers (the dispatch layer)
2714/// when assembling a third-party-channel deeplink:
2715/// `links.pidgr.com/c/{short_code}?t={token}`.
2716#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2717pub struct ResolveOrCreateShortCodeRequest {
2718 /// The campaign whose short-code is being resolved.
2719 /// Constraints: Required, must be a UUID and exist within the caller's organization.
2720 #[prost(string, tag="1")]
2721 pub campaign_id: ::prost::alloc::string::String,
2722}
2723/// Response carrying the resolved short-code. The same campaign always
2724/// resolves to the same code for its lifetime; the value is safe to
2725/// cache by the caller.
2726#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2727pub struct ResolveOrCreateShortCodeResponse {
2728 /// 8-character base62 short-code stable for the campaign's lifetime.
2729 #[prost(string, tag="1")]
2730 pub short_code: ::prost::alloc::string::String,
2731}
2732/// Request to look up a campaign by its public short-code. Called by the
2733/// native app when the recipient taps a third-party-channel deeplink and
2734/// the URL handler needs to route to the right campaign card. Designed to
2735/// be safe to call without authentication — the response carries no PII
2736/// and only enough context for the app to route correctly and show org
2737/// branding before the auth gate.
2738#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2739pub struct GetCampaignByShortCodeRequest {
2740 /// The 8-character short-code from the deeplink path.
2741 /// Constraints: Required, exactly 8 base62 characters.
2742 #[prost(string, tag="1")]
2743 pub short_code: ::prost::alloc::string::String,
2744}
2745/// Response carrying the minimum metadata the native app needs to route
2746/// the deeplink. Subject is the campaign's title text (already visible
2747/// in the recipient's inbox after dispatch — no new PII exposure). Body
2748/// content, audience size, delivery status and any other operational
2749/// fields are NOT included; the app fetches those via authenticated
2750/// `GetCampaign` after the recipient signs in.
2751#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2752pub struct GetCampaignByShortCodeResponse {
2753 /// Campaign UUID — the app uses this for the authenticated `GetCampaign`
2754 /// follow-up after the deeplink token validates.
2755 #[prost(string, tag="1")]
2756 pub campaign_id: ::prost::alloc::string::String,
2757 /// Organization UUID owning the campaign — lets the app pick the
2758 /// correct SSO / sign-in flow when the recipient is logged out.
2759 #[prost(string, tag="2")]
2760 pub org_id: ::prost::alloc::string::String,
2761 /// Display name of the organization for sign-in branding ("Sign in to
2762 /// Acme Inc to view this campaign"). Public information; the
2763 /// organization's profile already exposes it elsewhere.
2764 #[prost(string, tag="3")]
2765 pub organization_name: ::prost::alloc::string::String,
2766 /// Campaign subject (title). Same string the recipient already saw in
2767 /// their inbox; included so the deeplink interstitial can show
2768 /// "Acme Inc — All-hands Q3" before the auth gate.
2769 #[prost(string, tag="4")]
2770 pub subject: ::prost::alloc::string::String,
2771}
2772// ─── Messages ───────────────────────────────────────────────────────────────
2773
2774/// A registered device that can receive push notifications.
2775/// INTERNAL: This message is for server-side use only. Use DeviceSummary for API responses.
2776#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2777pub struct Device {
2778 /// Unique identifier for this device.
2779 /// Constraints: UUID format (36 characters).
2780 #[prost(string, tag="1")]
2781 pub device_id: ::prost::alloc::string::String,
2782 /// ID of the user who owns this device.
2783 /// Constraints: UUID format (36 characters).
2784 #[prost(string, tag="2")]
2785 pub user_id: ::prost::alloc::string::String,
2786 /// Mobile platform (iOS or Android).
2787 #[prost(enumeration="Platform", tag="3")]
2788 pub platform: i32,
2789 /// Push token used to send notifications to this device.
2790 #[prost(string, tag="4")]
2791 pub push_token: ::prost::alloc::string::String,
2792 /// Whether the device is currently active and eligible for push delivery.
2793 #[prost(bool, tag="5")]
2794 pub active: bool,
2795 /// Timestamp of the last activity from this device.
2796 #[prost(message, optional, tag="6")]
2797 pub last_seen: ::core::option::Option<::prost_types::Timestamp>,
2798 /// Timestamp when the device was first registered.
2799 #[prost(message, optional, tag="7")]
2800 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
2801}
2802/// A device summary safe for API responses — excludes sensitive push_token.
2803#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2804pub struct DeviceSummary {
2805 /// Unique identifier for this device.
2806 #[prost(string, tag="1")]
2807 pub device_id: ::prost::alloc::string::String,
2808 /// ID of the user who owns this device.
2809 #[prost(string, tag="2")]
2810 pub user_id: ::prost::alloc::string::String,
2811 /// Mobile platform (iOS or Android).
2812 #[prost(enumeration="Platform", tag="3")]
2813 pub platform: i32,
2814 /// Whether the device is currently active and eligible for push delivery.
2815 #[prost(bool, tag="4")]
2816 pub active: bool,
2817 /// Timestamp of the last activity from this device.
2818 #[prost(message, optional, tag="5")]
2819 pub last_seen: ::core::option::Option<::prost_types::Timestamp>,
2820 /// Timestamp when the device was first registered.
2821 #[prost(message, optional, tag="6")]
2822 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
2823}
2824/// Request to register a device for push notifications.
2825#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2826pub struct RegisterRequest {
2827 /// Client-generated unique device identifier.
2828 /// Constraints: UUID format (36 characters).
2829 #[prost(string, tag="1")]
2830 pub device_id: ::prost::alloc::string::String,
2831 /// Mobile platform of the device.
2832 #[prost(enumeration="Platform", tag="2")]
2833 pub platform: i32,
2834 /// Push token obtained from the push notification provider on the client.
2835 /// Constraints: Max length 4096 characters.
2836 #[prost(string, tag="3")]
2837 pub push_token: ::prost::alloc::string::String,
2838}
2839/// Response after registering a device.
2840#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2841pub struct RegisterResponse {
2842 /// The registered device summary (excludes push_token).
2843 #[prost(message, optional, tag="1")]
2844 pub device: ::core::option::Option<DeviceSummary>,
2845}
2846/// Request to deactivate a device, stopping push notifications.
2847#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2848pub struct DeactivateRequest {
2849 /// ID of the device to deactivate.
2850 /// Constraints: UUID format (36 characters).
2851 #[prost(string, tag="1")]
2852 pub device_id: ::prost::alloc::string::String,
2853}
2854/// Response after deactivating a device.
2855#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
2856pub struct DeactivateResponse {
2857 /// Whether the device was successfully deactivated.
2858 #[prost(bool, tag="1")]
2859 pub success: bool,
2860}
2861/// Request to list all devices for the authenticated user.
2862#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
2863pub struct ListDevicesRequest {
2864}
2865/// Response containing all devices for the user.
2866#[derive(Clone, PartialEq, ::prost::Message)]
2867pub struct ListDevicesResponse {
2868 /// List of devices registered to the authenticated user.
2869 #[prost(message, repeated, tag="1")]
2870 pub devices: ::prost::alloc::vec::Vec<DeviceSummary>,
2871}
2872/// Request to list devices for a specific member (admin use).
2873#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2874pub struct ListMemberDevicesRequest {
2875 /// ID of the user whose devices to list.
2876 /// Constraints: UUID format (36 characters).
2877 #[prost(string, tag="1")]
2878 pub user_id: ::prost::alloc::string::String,
2879}
2880/// Response containing all devices for the specified member.
2881#[derive(Clone, PartialEq, ::prost::Message)]
2882pub struct ListMemberDevicesResponse {
2883 /// List of devices registered to the specified user.
2884 #[prost(message, repeated, tag="1")]
2885 pub devices: ::prost::alloc::vec::Vec<DeviceSummary>,
2886}
2887// ─── Messages ───────────────────────────────────────────────────────────────
2888
2889/// User-configurable platform settings that apply across all clients.
2890/// All fields use their UNSPECIFIED/zero value to mean "no change" in updates.
2891#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2892pub struct UserSettings {
2893 /// Preferred color scheme for the UI.
2894 #[prost(enumeration="ThemePreference", tag="1")]
2895 pub theme_preference: i32,
2896 /// User's preferred language for the UI and push notifications.
2897 /// Empty string means "use organization default" or "auto-detect".
2898 /// Valid values: en, es, pt-BR, zh, ja.
2899 #[prost(string, tag="2")]
2900 pub preferred_locale: ::prost::alloc::string::String,
2901}
2902/// Structured profile attributes for a user within an organization.
2903/// Populated through admin invitation, mobile onboarding, or SSO attribute sync.
2904#[derive(Clone, PartialEq, ::prost::Message)]
2905pub struct UserProfile {
2906 /// User's given name.
2907 /// Constraints: Max length 200 characters.
2908 #[prost(string, tag="1")]
2909 pub first_name: ::prost::alloc::string::String,
2910 /// User's family name.
2911 /// Constraints: Max length 200 characters.
2912 #[prost(string, tag="2")]
2913 pub last_name: ::prost::alloc::string::String,
2914 /// Department or team within the organization.
2915 /// Constraints: Max length 200 characters.
2916 #[prost(string, tag="3")]
2917 pub department: ::prost::alloc::string::String,
2918 /// Job title.
2919 /// Constraints: Max length 200 characters.
2920 #[prost(string, tag="4")]
2921 pub title: ::prost::alloc::string::String,
2922 /// Phone number.
2923 /// Constraints: Max length 200 characters.
2924 #[prost(string, tag="5")]
2925 pub phone: ::prost::alloc::string::String,
2926 /// Office or geographic location.
2927 /// Constraints: Max length 200 characters.
2928 #[prost(string, tag="6")]
2929 pub location: ::prost::alloc::string::String,
2930 /// Organization-specific employee identifier.
2931 /// Constraints: Max length 200 characters.
2932 #[prost(string, tag="7")]
2933 pub employee_id: ::prost::alloc::string::String,
2934 /// Display name of the user's direct manager.
2935 /// Constraints: Max length 200 characters.
2936 #[prost(string, tag="8")]
2937 pub manager_name: ::prost::alloc::string::String,
2938 /// Employment start date in ISO 8601 format (YYYY-MM-DD).
2939 /// Constraints: Max length 200 characters.
2940 #[prost(string, tag="9")]
2941 pub start_date: ::prost::alloc::string::String,
2942 /// Organization-defined custom attributes for fields not covered by the fixed schema.
2943 /// Constraints: Max 50 entries. Key max length 100 characters, value max length 1000 characters.
2944 #[prost(map="string, string", tag="10")]
2945 pub custom_attributes: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
2946 /// UUID of the user's direct manager within the same organization.
2947 /// Populated from SCIM enterprise extension (manager.value), manual admin
2948 /// assignment, or SSO attribute mapping. Empty if not set.
2949 #[prost(string, tag="11")]
2950 pub manager_id: ::prost::alloc::string::String,
2951}
2952/// A user within an organization.
2953#[derive(Clone, PartialEq, ::prost::Message)]
2954pub struct User {
2955 /// Unique identifier for the user (internal platform UUID, not identity provider subject ID).
2956 #[prost(string, tag="1")]
2957 pub id: ::prost::alloc::string::String,
2958 /// User's email address.
2959 /// Constraints: Max length 254 characters (RFC 5321).
2960 #[prost(string, tag="2")]
2961 pub email: ::prost::alloc::string::String,
2962 /// User's display name.
2963 /// Constraints: Max length 200 characters.
2964 #[prost(string, tag="3")]
2965 pub name: ::prost::alloc::string::String,
2966 /// Current account status.
2967 #[prost(enumeration="UserStatus", tag="5")]
2968 pub status: i32,
2969 /// Timestamp when the user was created.
2970 #[prost(message, optional, tag="6")]
2971 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
2972 /// The user's role with its permission set.
2973 #[prost(message, optional, tag="7")]
2974 pub role: ::core::option::Option<Role>,
2975 /// ID of the user's role (for assignment operations).
2976 #[prost(string, tag="8")]
2977 pub role_id: ::prost::alloc::string::String,
2978 /// Structured profile attributes (department, title, etc.).
2979 /// May be empty if the user has not completed their profile.
2980 #[prost(message, optional, tag="9")]
2981 pub profile: ::core::option::Option<UserProfile>,
2982 /// Whether data processing is restricted for this user (GDPR Art. 18).
2983 /// When true, the user is excluded from campaign audiences by default.
2984 #[prost(bool, tag="10")]
2985 pub processing_restricted: bool,
2986 /// Data governance region override. Empty string means "inherit from org default".
2987 /// Valid values: EU, LATAM, BR, APAC, US.
2988 #[prost(string, tag="11")]
2989 pub data_governance_region: ::prost::alloc::string::String,
2990}
2991// ─── Enums ──────────────────────────────────────────────────────────────────
2992
2993/// Lifecycle status of a user account.
2994#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2995#[repr(i32)]
2996pub enum UserStatus {
2997 /// Default value; not a valid status.
2998 Unspecified = 0,
2999 /// User has been invited but has not completed onboarding.
3000 Invited = 1,
3001 /// User is active and can receive messages.
3002 Active = 2,
3003 /// User has been deactivated and will not receive messages.
3004 Deactivated = 3,
3005}
3006impl UserStatus {
3007 /// String value of the enum field names used in the ProtoBuf definition.
3008 ///
3009 /// The values are not transformed in any way and thus are considered stable
3010 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
3011 pub fn as_str_name(&self) -> &'static str {
3012 match self {
3013 Self::Unspecified => "USER_STATUS_UNSPECIFIED",
3014 Self::Invited => "USER_STATUS_INVITED",
3015 Self::Active => "USER_STATUS_ACTIVE",
3016 Self::Deactivated => "USER_STATUS_DEACTIVATED",
3017 }
3018 }
3019 /// Creates an enum from field names used in the ProtoBuf definition.
3020 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
3021 match value {
3022 "USER_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
3023 "USER_STATUS_INVITED" => Some(Self::Invited),
3024 "USER_STATUS_ACTIVE" => Some(Self::Active),
3025 "USER_STATUS_DEACTIVATED" => Some(Self::Deactivated),
3026 _ => None,
3027 }
3028 }
3029}
3030/// User's preferred color scheme.
3031#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
3032#[repr(i32)]
3033pub enum ThemePreference {
3034 /// Default value; treated as SYSTEM when reading, "no change" when updating.
3035 Unspecified = 0,
3036 /// Always use light mode regardless of system setting.
3037 Light = 1,
3038 /// Always use dark mode regardless of system setting.
3039 Dark = 2,
3040 /// Follow the operating system or browser preference.
3041 System = 3,
3042}
3043impl ThemePreference {
3044 /// String value of the enum field names used in the ProtoBuf definition.
3045 ///
3046 /// The values are not transformed in any way and thus are considered stable
3047 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
3048 pub fn as_str_name(&self) -> &'static str {
3049 match self {
3050 Self::Unspecified => "THEME_PREFERENCE_UNSPECIFIED",
3051 Self::Light => "THEME_PREFERENCE_LIGHT",
3052 Self::Dark => "THEME_PREFERENCE_DARK",
3053 Self::System => "THEME_PREFERENCE_SYSTEM",
3054 }
3055 }
3056 /// Creates an enum from field names used in the ProtoBuf definition.
3057 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
3058 match value {
3059 "THEME_PREFERENCE_UNSPECIFIED" => Some(Self::Unspecified),
3060 "THEME_PREFERENCE_LIGHT" => Some(Self::Light),
3061 "THEME_PREFERENCE_DARK" => Some(Self::Dark),
3062 "THEME_PREFERENCE_SYSTEM" => Some(Self::System),
3063 _ => None,
3064 }
3065 }
3066}
3067// ─── Messages ───────────────────────────────────────────────────────────────
3068
3069/// A named collection of users within an organization, used for campaign
3070/// audience targeting (recipient groups).
3071#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3072pub struct Group {
3073 /// Unique identifier for the group.
3074 #[prost(string, tag="1")]
3075 pub id: ::prost::alloc::string::String,
3076 /// Human-readable display name (unique within the organization).
3077 /// Constraints: Max length 200 characters.
3078 #[prost(string, tag="2")]
3079 pub name: ::prost::alloc::string::String,
3080 /// Optional description of the group's purpose.
3081 /// Constraints: Max length 1000 characters.
3082 #[prost(string, tag="3")]
3083 pub description: ::prost::alloc::string::String,
3084 /// Number of users currently in the group.
3085 #[prost(int32, tag="4")]
3086 pub member_count: i32,
3087 /// Timestamp when the group was created.
3088 #[prost(message, optional, tag="5")]
3089 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
3090 /// Timestamp when the group was last updated.
3091 #[prost(message, optional, tag="6")]
3092 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
3093 /// Whether this is the organization's default group (cannot be deleted or renamed).
3094 #[prost(bool, tag="7")]
3095 pub is_default: bool,
3096 /// ID of the user who created this group. Empty for system-seeded defaults.
3097 #[prost(string, tag="8")]
3098 pub created_by: ::prost::alloc::string::String,
3099}
3100/// Request to create a new group.
3101#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3102pub struct CreateGroupRequest {
3103 /// Display name for the group. Required.
3104 /// Constraints: Max length 200 characters.
3105 #[prost(string, tag="1")]
3106 pub name: ::prost::alloc::string::String,
3107 /// Optional description.
3108 /// Constraints: Max length 1000 characters.
3109 #[prost(string, tag="2")]
3110 pub description: ::prost::alloc::string::String,
3111}
3112/// Response after creating a group.
3113#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3114pub struct CreateGroupResponse {
3115 /// The newly created group.
3116 #[prost(message, optional, tag="1")]
3117 pub group: ::core::option::Option<Group>,
3118}
3119/// Request to retrieve a group by ID.
3120#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3121pub struct GetGroupRequest {
3122 /// ID of the group to retrieve. Required.
3123 #[prost(string, tag="1")]
3124 pub group_id: ::prost::alloc::string::String,
3125}
3126/// Response containing the requested group.
3127#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3128pub struct GetGroupResponse {
3129 /// The requested group.
3130 #[prost(message, optional, tag="1")]
3131 pub group: ::core::option::Option<Group>,
3132}
3133/// Request to list groups in the organization with pagination.
3134#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3135pub struct ListGroupsRequest {
3136 /// Pagination parameters.
3137 #[prost(message, optional, tag="1")]
3138 pub pagination: ::core::option::Option<Pagination>,
3139}
3140/// Response containing a page of groups.
3141#[derive(Clone, PartialEq, ::prost::Message)]
3142pub struct ListGroupsResponse {
3143 /// Groups in this page.
3144 #[prost(message, repeated, tag="1")]
3145 pub groups: ::prost::alloc::vec::Vec<Group>,
3146 /// Pagination metadata for fetching subsequent pages.
3147 #[prost(message, optional, tag="2")]
3148 pub pagination_meta: ::core::option::Option<PaginationMeta>,
3149}
3150/// Request to update a group's name and/or description.
3151#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3152pub struct UpdateGroupRequest {
3153 /// ID of the group to update. Required.
3154 #[prost(string, tag="1")]
3155 pub group_id: ::prost::alloc::string::String,
3156 /// New display name. If empty, the name is not changed.
3157 /// Default groups cannot be renamed.
3158 /// Constraints: Max length 200 characters.
3159 #[prost(string, tag="2")]
3160 pub name: ::prost::alloc::string::String,
3161 /// New description. If empty, the description is not changed.
3162 /// Constraints: Max length 1000 characters.
3163 #[prost(string, tag="3")]
3164 pub description: ::prost::alloc::string::String,
3165}
3166/// Response after updating a group.
3167#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3168pub struct UpdateGroupResponse {
3169 /// The updated group.
3170 #[prost(message, optional, tag="1")]
3171 pub group: ::core::option::Option<Group>,
3172}
3173/// Request to delete a group.
3174#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3175pub struct DeleteGroupRequest {
3176 /// ID of the group to delete. Required.
3177 /// Default groups cannot be deleted.
3178 #[prost(string, tag="1")]
3179 pub group_id: ::prost::alloc::string::String,
3180}
3181/// Response after deleting a group.
3182#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3183pub struct DeleteGroupResponse {
3184}
3185/// Request to add users to a group.
3186#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3187pub struct AddGroupMembersRequest {
3188 /// ID of the group to add members to. Required.
3189 #[prost(string, tag="1")]
3190 pub group_id: ::prost::alloc::string::String,
3191 /// IDs of users to add. Must belong to the same organization.
3192 /// Adding an existing member is a no-op (idempotent).
3193 /// Constraints: Max 100 user IDs per request.
3194 #[prost(string, repeated, tag="2")]
3195 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
3196}
3197/// Response after adding group members.
3198#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3199pub struct AddGroupMembersResponse {
3200 /// The group with updated member_count.
3201 #[prost(message, optional, tag="1")]
3202 pub group: ::core::option::Option<Group>,
3203}
3204/// Request to remove users from a group.
3205#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3206pub struct RemoveGroupMembersRequest {
3207 /// ID of the group to remove members from. Required.
3208 #[prost(string, tag="1")]
3209 pub group_id: ::prost::alloc::string::String,
3210 /// IDs of users to remove. Removing a non-member is a no-op (idempotent).
3211 /// Constraints: Max 100 user IDs per request.
3212 #[prost(string, repeated, tag="2")]
3213 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
3214}
3215/// Response after removing group members.
3216#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3217pub struct RemoveGroupMembersResponse {
3218 /// The group with updated member_count.
3219 #[prost(message, optional, tag="1")]
3220 pub group: ::core::option::Option<Group>,
3221}
3222/// Request to list members of a group with pagination.
3223#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3224pub struct ListGroupMembersRequest {
3225 /// ID of the group whose members to list. Required.
3226 #[prost(string, tag="1")]
3227 pub group_id: ::prost::alloc::string::String,
3228 /// Pagination parameters.
3229 #[prost(message, optional, tag="2")]
3230 pub pagination: ::core::option::Option<Pagination>,
3231}
3232/// Response containing a page of group members.
3233#[derive(Clone, PartialEq, ::prost::Message)]
3234pub struct ListGroupMembersResponse {
3235 /// Users in this page.
3236 #[prost(message, repeated, tag="1")]
3237 pub users: ::prost::alloc::vec::Vec<User>,
3238 /// Pagination metadata for fetching subsequent pages.
3239 #[prost(message, optional, tag="2")]
3240 pub pagination_meta: ::core::option::Option<PaginationMeta>,
3241}
3242/// A group membership entry for batch lookups.
3243#[derive(Clone, PartialEq, ::prost::Message)]
3244pub struct UserGroupMembership {
3245 /// ID of the user.
3246 #[prost(string, tag="1")]
3247 pub user_id: ::prost::alloc::string::String,
3248 /// Groups the user belongs to.
3249 #[prost(message, repeated, tag="2")]
3250 pub groups: ::prost::alloc::vec::Vec<Group>,
3251}
3252/// Request to get group memberships for a batch of users.
3253#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3254pub struct GetUserGroupMembershipsRequest {
3255 /// IDs of users to look up. Required.
3256 /// Constraints: Max 200 user IDs per request.
3257 #[prost(string, repeated, tag="1")]
3258 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
3259}
3260/// Response containing group memberships for the requested users.
3261#[derive(Clone, PartialEq, ::prost::Message)]
3262pub struct GetUserGroupMembershipsResponse {
3263 /// Group memberships per user. Only users with at least one group are included.
3264 #[prost(message, repeated, tag="1")]
3265 pub memberships: ::prost::alloc::vec::Vec<UserGroupMembership>,
3266}
3267// ─── Messages ───────────────────────────────────────────────────────────────
3268
3269/// A single touch event captured from the mobile app.
3270#[derive(Clone, PartialEq, ::prost::Message)]
3271pub struct TouchEvent {
3272 /// Screen name from React Navigation route.
3273 /// Constraints: Max length 200 characters.
3274 #[prost(string, tag="1")]
3275 pub screen_name: ::prost::alloc::string::String,
3276 /// Horizontal coordinate as a percentage of screen width (0.0–1.0).
3277 /// Constraints: Range 0.0 to 1.0 inclusive.
3278 #[prost(float, tag="2")]
3279 pub x_pct: f32,
3280 /// Vertical coordinate as a percentage of screen height (0.0–1.0).
3281 /// Constraints: Range 0.0 to 1.0 inclusive.
3282 #[prost(float, tag="3")]
3283 pub y_pct: f32,
3284 /// Type of touch event.
3285 #[prost(enumeration="TouchEventType", tag="4")]
3286 pub event_type: i32,
3287 /// Screen width in device pixels at the time of capture.
3288 #[prost(int32, tag="5")]
3289 pub screen_width: i32,
3290 /// Screen height in device pixels at the time of capture.
3291 #[prost(int32, tag="6")]
3292 pub screen_height: i32,
3293 /// Client-side timestamp when the touch occurred.
3294 #[prost(message, optional, tag="7")]
3295 pub client_timestamp: ::core::option::Option<::prost_types::Timestamp>,
3296 /// Campaign ID if the touch occurred during a campaign message view.
3297 /// Empty string for organic (non-campaign) navigation.
3298 #[prost(string, tag="8")]
3299 pub campaign_id: ::prost::alloc::string::String,
3300}
3301/// Request to ingest a batch of touch events from the mobile app.
3302#[derive(Clone, PartialEq, ::prost::Message)]
3303pub struct IngestTouchEventsRequest {
3304 /// Batch of touch events to ingest.
3305 /// Constraints: Max 100 events per batch.
3306 #[prost(message, repeated, tag="1")]
3307 pub events: ::prost::alloc::vec::Vec<TouchEvent>,
3308}
3309/// Response after ingesting touch events.
3310#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3311pub struct IngestTouchEventsResponse {
3312 /// Number of events successfully ingested.
3313 #[prost(int32, tag="1")]
3314 pub ingested_count: i32,
3315}
3316/// A single aggregated data point in a heatmap grid cell.
3317#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3318pub struct HeatmapDataPoint {
3319 /// Grid cell horizontal center as a percentage (0.0–1.0).
3320 #[prost(float, tag="1")]
3321 pub x_pct: f32,
3322 /// Grid cell vertical center as a percentage (0.0–1.0).
3323 #[prost(float, tag="2")]
3324 pub y_pct: f32,
3325 /// Aggregated value for this cell (count, median, or z-score depending on mode).
3326 #[prost(float, tag="3")]
3327 pub value: f32,
3328}
3329/// Request to query aggregated heatmap data for a screen.
3330#[derive(Clone, PartialEq, ::prost::Message)]
3331pub struct QueryHeatmapDataRequest {
3332 /// Screen name to query.
3333 /// Constraints: Max length 200 characters.
3334 #[prost(string, tag="1")]
3335 pub screen_name: ::prost::alloc::string::String,
3336 /// Start of the time range filter (inclusive).
3337 #[prost(message, optional, tag="2")]
3338 pub date_from: ::core::option::Option<::prost_types::Timestamp>,
3339 /// End of the time range filter (inclusive).
3340 #[prost(message, optional, tag="3")]
3341 pub date_to: ::core::option::Option<::prost_types::Timestamp>,
3342 /// Optional: filter by campaign ID.
3343 /// Constraints: UUID format (36 characters).
3344 #[prost(string, tag="4")]
3345 pub campaign_id: ::prost::alloc::string::String,
3346 /// Grid resolution for coordinate rounding. Default: 0.02 (50×50 grid).
3347 /// Constraints: Range 0.005 to 0.1.
3348 #[prost(float, tag="6")]
3349 pub grid_resolution: f32,
3350 /// Aggregation mode (TOTAL or MEDIAN).
3351 #[prost(enumeration="HeatmapMode", tag="7")]
3352 pub mode: i32,
3353 /// Optional: filter by event types. Empty list means all types.
3354 #[prost(enumeration="TouchEventType", repeated, tag="8")]
3355 pub event_types: ::prost::alloc::vec::Vec<i32>,
3356}
3357/// Response containing aggregated heatmap data.
3358#[derive(Clone, PartialEq, ::prost::Message)]
3359pub struct QueryHeatmapDataResponse {
3360 /// Aggregated data points for heatmap rendering.
3361 #[prost(message, repeated, tag="1")]
3362 pub data_points: ::prost::alloc::vec::Vec<HeatmapDataPoint>,
3363 /// URL to a mobile-captured screenshot for this screen, if available.
3364 /// Empty string when no screenshot exists.
3365 #[prost(string, tag="3")]
3366 pub screenshot_url: ::prost::alloc::string::String,
3367 /// Whether per-cohort bucket breakdowns are available (k >= 5).
3368 #[prost(bool, tag="4")]
3369 pub cohort_enabled: bool,
3370}
3371/// Request to upload a screenshot captured from the mobile app.
3372#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3373pub struct UploadScreenshotRequest {
3374 /// Screen name matching React Navigation route (e.g. "MessageDetail::<campaign_uuid>").
3375 /// Constraints: Max length 200 characters.
3376 #[prost(string, tag="1")]
3377 pub screen_name: ::prost::alloc::string::String,
3378 /// App version that captured the screenshot (e.g. "1.15.0").
3379 #[prost(string, tag="2")]
3380 pub app_version: ::prost::alloc::string::String,
3381 /// PNG image data.
3382 /// Constraints: Max 512KB.
3383 #[prost(bytes="vec", tag="3")]
3384 pub image_data: ::prost::alloc::vec::Vec<u8>,
3385}
3386/// Response after uploading a screenshot.
3387#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3388pub struct UploadScreenshotResponse {
3389 /// S3 URL where the screenshot was stored.
3390 #[prost(string, tag="1")]
3391 pub url: ::prost::alloc::string::String,
3392}
3393/// A screen screenshot stored as a static asset.
3394#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3395pub struct ScreenScreenshot {
3396 /// Screen name matching React Navigation route.
3397 #[prost(string, tag="1")]
3398 pub screen_name: ::prost::alloc::string::String,
3399 /// S3 URL to the screenshot image.
3400 #[prost(string, tag="2")]
3401 pub url: ::prost::alloc::string::String,
3402 /// App version this screenshot corresponds to.
3403 #[prost(string, tag="3")]
3404 pub app_version: ::prost::alloc::string::String,
3405}
3406/// Request to list available screen screenshots.
3407#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3408pub struct ListScreenshotsRequest {
3409}
3410/// Response containing available screen screenshots.
3411#[derive(Clone, PartialEq, ::prost::Message)]
3412pub struct ListScreenshotsResponse {
3413 /// Available screen screenshots with their URLs and versions.
3414 #[prost(message, repeated, tag="1")]
3415 pub screenshots: ::prost::alloc::vec::Vec<ScreenScreenshot>,
3416}
3417// ─── Enums ──────────────────────────────────────────────────────────────────
3418
3419/// Type of touch event captured on the mobile app.
3420#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
3421#[repr(i32)]
3422pub enum TouchEventType {
3423 /// Default value; not a valid event type.
3424 Unspecified = 0,
3425 /// A single tap on the screen.
3426 Tap = 1,
3427 /// A long press (held for 500ms+).
3428 LongPress = 2,
3429 /// A periodic scroll position sample (viewport midpoint every 2s).
3430 Scroll = 3,
3431 /// The user tapped an action button (e.g. "Acknowledge").
3432 ActionClick = 4,
3433}
3434impl TouchEventType {
3435 /// String value of the enum field names used in the ProtoBuf definition.
3436 ///
3437 /// The values are not transformed in any way and thus are considered stable
3438 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
3439 pub fn as_str_name(&self) -> &'static str {
3440 match self {
3441 Self::Unspecified => "TOUCH_EVENT_TYPE_UNSPECIFIED",
3442 Self::Tap => "TOUCH_EVENT_TYPE_TAP",
3443 Self::LongPress => "TOUCH_EVENT_TYPE_LONG_PRESS",
3444 Self::Scroll => "TOUCH_EVENT_TYPE_SCROLL",
3445 Self::ActionClick => "TOUCH_EVENT_TYPE_ACTION_CLICK",
3446 }
3447 }
3448 /// Creates an enum from field names used in the ProtoBuf definition.
3449 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
3450 match value {
3451 "TOUCH_EVENT_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
3452 "TOUCH_EVENT_TYPE_TAP" => Some(Self::Tap),
3453 "TOUCH_EVENT_TYPE_LONG_PRESS" => Some(Self::LongPress),
3454 "TOUCH_EVENT_TYPE_SCROLL" => Some(Self::Scroll),
3455 "TOUCH_EVENT_TYPE_ACTION_CLICK" => Some(Self::ActionClick),
3456 _ => None,
3457 }
3458 }
3459}
3460/// Aggregation mode for heatmap data queries.
3461#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
3462#[repr(i32)]
3463pub enum HeatmapMode {
3464 /// Default value; not a valid mode.
3465 Unspecified = 0,
3466 /// Sum of all cohort buckets' touches per grid cell (default).
3467 Total = 1,
3468 /// Median touch count per grid cell across cohort buckets.
3469 Median = 2,
3470}
3471impl HeatmapMode {
3472 /// String value of the enum field names used in the ProtoBuf definition.
3473 ///
3474 /// The values are not transformed in any way and thus are considered stable
3475 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
3476 pub fn as_str_name(&self) -> &'static str {
3477 match self {
3478 Self::Unspecified => "HEATMAP_MODE_UNSPECIFIED",
3479 Self::Total => "HEATMAP_MODE_TOTAL",
3480 Self::Median => "HEATMAP_MODE_MEDIAN",
3481 }
3482 }
3483 /// Creates an enum from field names used in the ProtoBuf definition.
3484 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
3485 match value {
3486 "HEATMAP_MODE_UNSPECIFIED" => Some(Self::Unspecified),
3487 "HEATMAP_MODE_TOTAL" => Some(Self::Total),
3488 "HEATMAP_MODE_MEDIAN" => Some(Self::Median),
3489 _ => None,
3490 }
3491 }
3492}
3493// ─── Messages ───────────────────────────────────────────────────────────────
3494
3495/// A single entry in a user's inbox, combining a message with its delivery state.
3496#[derive(Clone, PartialEq, ::prost::Message)]
3497pub struct InboxEntry {
3498 /// ID of the delivery record for this inbox entry.
3499 /// Constraints: UUID format (36 characters).
3500 #[prost(string, tag="1")]
3501 pub delivery_id: ::prost::alloc::string::String,
3502 /// The fully rendered message content.
3503 #[prost(message, optional, tag="2")]
3504 pub message: ::core::option::Option<Message>,
3505 /// Current delivery status (e.g. DELIVERED, ACKNOWLEDGED).
3506 #[prost(enumeration="DeliveryStatus", tag="3")]
3507 pub status: i32,
3508 /// Whether the user has read this message.
3509 #[prost(bool, tag="4")]
3510 pub read: bool,
3511 /// Timestamp when the message was received in the inbox.
3512 #[prost(message, optional, tag="5")]
3513 pub received_at: ::core::option::Option<::prost_types::Timestamp>,
3514 /// Discriminator: PRIMARY for normal deliveries, ESCALATION for delivery-grade
3515 /// escalations. Mirrors Delivery.kind so inbox-sync clients can branch on the
3516 /// same dimension as listDeliveries clients.
3517 #[prost(enumeration="delivery::Kind", tag="6")]
3518 pub kind: i32,
3519 /// For ESCALATION entries, the UUID of the unacked delivery that triggered this
3520 /// entry. Empty for PRIMARY entries.
3521 #[prost(string, tag="7")]
3522 pub parent_delivery_id: ::prost::alloc::string::String,
3523 /// The locale the body actually rendered in after fallback resolution. Empty
3524 /// for legacy/PRIMARY entries.
3525 #[prost(string, tag="8")]
3526 pub rendered_locale: ::prost::alloc::string::String,
3527 /// Optional out-of-band context mirrored from the underlying delivery.
3528 /// See `DeliveryMetadata` for which delivery kinds populate which fields.
3529 /// Empty for PRIMARY entries.
3530 #[prost(message, optional, tag="9")]
3531 pub metadata: ::core::option::Option<DeliveryMetadata>,
3532}
3533/// Request to sync inbox entries since a given timestamp.
3534#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3535pub struct SyncRequest {
3536 /// Fetch entries newer than this timestamp. Omit for initial sync.
3537 #[prost(message, optional, tag="1")]
3538 pub since: ::core::option::Option<::prost_types::Timestamp>,
3539 /// Maximum number of entries to return.
3540 /// Constraints: Valid range 1 to 200.
3541 #[prost(int32, tag="2")]
3542 pub limit: i32,
3543}
3544/// Response containing synced inbox entries.
3545#[derive(Clone, PartialEq, ::prost::Message)]
3546pub struct SyncResponse {
3547 /// Inbox entries newer than the requested timestamp.
3548 #[prost(message, repeated, tag="1")]
3549 pub entries: ::prost::alloc::vec::Vec<InboxEntry>,
3550 /// Cursor timestamp to use for the next sync call.
3551 #[prost(message, optional, tag="2")]
3552 pub next_since: ::core::option::Option<::prost_types::Timestamp>,
3553}
3554/// Request to mark a message as read.
3555#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3556pub struct MarkReadRequest {
3557 /// ID of the delivery to mark as read.
3558 /// Constraints: UUID format (36 characters).
3559 #[prost(string, tag="1")]
3560 pub delivery_id: ::prost::alloc::string::String,
3561}
3562/// Response after marking a message as read.
3563#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3564pub struct MarkReadResponse {
3565 /// Whether the read status was successfully updated.
3566 #[prost(bool, tag="1")]
3567 pub success: bool,
3568}
3569/// Request to retrieve a single message by delivery ID.
3570#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3571pub struct GetMessageRequest {
3572 /// ID of the delivery to retrieve.
3573 /// Constraints: UUID format (36 characters).
3574 #[prost(string, tag="1")]
3575 pub delivery_id: ::prost::alloc::string::String,
3576}
3577/// Response containing the requested inbox entry.
3578#[derive(Clone, PartialEq, ::prost::Message)]
3579pub struct GetMessageResponse {
3580 /// The inbox entry for the requested delivery.
3581 #[prost(message, optional, tag="1")]
3582 pub entry: ::core::option::Option<InboxEntry>,
3583}
3584// ─── Messages ───────────────────────────────────────────────────────────────
3585
3586/// A behavioral archetype describing a cohort pattern (never an individual).
3587/// Derived from k-anonymized, DP-noised behavioral feature vectors.
3588#[derive(Clone, PartialEq, ::prost::Message)]
3589pub struct Archetype {
3590 /// Human-readable label (e.g., "Swift Acknowledger", "Thorough Reader").
3591 #[prost(string, tag="1")]
3592 pub label: ::prost::alloc::string::String,
3593 /// Description of the behavioral pattern this archetype represents.
3594 #[prost(string, tag="2")]
3595 pub description: ::prost::alloc::string::String,
3596 /// Proportion of the group that belongs to this archetype (0.0-1.0).
3597 #[prost(float, tag="3")]
3598 pub percentage: f32,
3599 /// Centroid of the behavioral feature vector for this archetype.
3600 /// Keys are stable dimension names from the feature extractor
3601 /// vocabulary (e.g., "tap_density", "engagement_depth",
3602 /// "scroll_velocity_p50", "idle_gap_p75"). Single-letter keys are
3603 /// reserved for backward compatibility with pre-v0.64 servers and
3604 /// SHALL be ignored by clients.
3605 #[prost(map="string, double", tag="4")]
3606 pub feature_centroid: ::std::collections::HashMap<::prost::alloc::string::String, f64>,
3607 /// Per-dimension distribution of the archetype's members. Lets the
3608 /// admin render percentile bands instead of single-point centroids.
3609 /// Absent until at least k members exist in the cluster. Keys mirror
3610 /// `feature_centroid` keys.
3611 #[prost(map="string, message", tag="5")]
3612 pub feature_breakdown: ::std::collections::HashMap<::prost::alloc::string::String, DimensionStats>,
3613 /// Tap density heatmap aggregated across sessions for this
3614 /// archetype. Cohort-level only — never per-session timing.
3615 /// Absent when fewer than k sessions have tap data.
3616 #[prost(message, optional, tag="6")]
3617 pub tap_heatmap: ::core::option::Option<TapHeatmap>,
3618 /// Forecast of cluster share at fixed horizons (7/14/30/90 days).
3619 /// Absent during cold start before historical clustering runs exist
3620 /// to extrapolate from.
3621 #[prost(message, optional, tag="7")]
3622 pub forecast: ::core::option::Option<ArchetypeForecast>,
3623 /// Sessions that sit at the median and quartiles of the archetype's
3624 /// centroid distance, ranked by distance. Bounded at three entries.
3625 /// Absent until at least 50 sessions have been scored.
3626 /// Sessions can come from any client that emits to ReplayService —
3627 /// mobile (iOS, Android) or desktop (macOS, Windows, Linux).
3628 #[prost(message, repeated, tag="8")]
3629 pub exemplar_sessions: ::prost::alloc::vec::Vec<ExemplarSession>,
3630 /// Per-screen dwell time distribution, derived from session replay.
3631 /// Absent when fewer than k sessions per screen exist.
3632 #[prost(message, optional, tag="9")]
3633 pub screen_dwell: ::core::option::Option<ScreenDwell>,
3634 /// End-to-end response latencies (push delivered → read → ack) for
3635 /// members of this archetype, as percentiles. Absent until at least
3636 /// k campaign deliveries have been recorded for this archetype.
3637 #[prost(message, optional, tag="10")]
3638 pub response_timeline: ::core::option::Option<ResponseTimeline>,
3639 /// Where this archetype came from. UNSPECIFIED on responses from
3640 /// pre-v0.81 servers; clients SHOULD treat UNSPECIFIED as ML for
3641 /// backward compatibility (provisional output is always labelled).
3642 #[prost(enumeration="ArchetypeSource", tag="11")]
3643 pub source: i32,
3644}
3645/// Per-dimension distribution stats for one feature dimension within
3646/// an archetype's cohort. All values are in the same units as
3647/// `Archetype.feature_centroid`. Used to render percentile bands on
3648/// the admin's behavioral profile panel.
3649#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3650pub struct DimensionStats {
3651 /// Centroid value (same as Archetype.feature_centroid\[key\]).
3652 #[prost(double, tag="1")]
3653 pub centroid: f64,
3654 /// 25th percentile across the archetype's members.
3655 #[prost(double, tag="2")]
3656 pub p25: f64,
3657 /// Median across the archetype's members.
3658 #[prost(double, tag="3")]
3659 pub p50: f64,
3660 /// 75th percentile across the archetype's members.
3661 #[prost(double, tag="4")]
3662 pub p75: f64,
3663 /// Median across the entire group (all archetypes), included so the
3664 /// admin can render "this archetype is X% above group median".
3665 #[prost(double, tag="5")]
3666 pub group_p50: f64,
3667}
3668/// A density grid of tap activity for one archetype, normalized to
3669/// \[0.0, 1.0\] where 1.0 is the hottest cell in the cohort. Cohort-
3670/// level only.
3671#[derive(Clone, PartialEq, ::prost::Message)]
3672pub struct TapHeatmap {
3673 /// Width of the density grid in cells.
3674 #[prost(int32, tag="1")]
3675 pub width: i32,
3676 /// Height of the density grid in cells.
3677 #[prost(int32, tag="2")]
3678 pub height: i32,
3679 /// Row-major density values, length must equal width*height. All in
3680 /// \[0.0, 1.0\].
3681 #[prost(double, repeated, tag="3")]
3682 pub values: ::prost::alloc::vec::Vec<f64>,
3683 /// Number of sessions aggregated. Always >= MinFeatureVectorsForClustering
3684 /// when the field is present.
3685 #[prost(int32, tag="4")]
3686 pub session_count: i32,
3687 /// Optional per-event-type breakdown. When present, the writer
3688 /// SHALL emit one entry for each event type in the source data
3689 /// (TAP, LONG_PRESS, SCROLL, ACTION_CLICK).
3690 #[prost(message, repeated, tag="5")]
3691 pub layers: ::prost::alloc::vec::Vec<TapHeatmapLayer>,
3692}
3693/// One per-event-type layer of a TapHeatmap.
3694#[derive(Clone, PartialEq, ::prost::Message)]
3695pub struct TapHeatmapLayer {
3696 /// Event type this layer represents (e.g., "TAP", "LONG_PRESS",
3697 /// "SCROLL", "ACTION_CLICK").
3698 #[prost(string, tag="1")]
3699 pub event_type: ::prost::alloc::string::String,
3700 /// Row-major density values, same dimensions as the parent
3701 /// TapHeatmap. Independently normalized to \[0.0, 1.0\].
3702 #[prost(double, repeated, tag="2")]
3703 pub values: ::prost::alloc::vec::Vec<f64>,
3704}
3705/// Predicted cluster share at fixed horizons with confidence bands.
3706#[derive(Clone, PartialEq, ::prost::Message)]
3707pub struct ArchetypeForecast {
3708 /// Horizons in increasing days. Always one entry each for 7, 14,
3709 /// 30, and 90 days when the field is present.
3710 #[prost(message, repeated, tag="1")]
3711 pub horizons: ::prost::alloc::vec::Vec<ForecastHorizon>,
3712}
3713/// Predicted share at one horizon with a 90% prediction interval.
3714#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3715pub struct ForecastHorizon {
3716 /// Horizon length in days (one of: 7, 14, 30, 90).
3717 #[prost(int32, tag="1")]
3718 pub days: i32,
3719 /// Predicted fraction of the group falling in this archetype at the
3720 /// horizon (0.0-1.0).
3721 #[prost(double, tag="2")]
3722 pub predicted_share: f64,
3723 /// 5th-percentile lower bound of the prediction interval.
3724 #[prost(double, tag="3")]
3725 pub lower: f64,
3726 /// 95th-percentile upper bound of the prediction interval.
3727 #[prost(double, tag="4")]
3728 pub upper: f64,
3729 /// Confidence in this horizon's prediction.
3730 #[prost(enumeration="ConfidenceLevel", tag="5")]
3731 pub confidence: i32,
3732}
3733/// Pointer to a representative session for one archetype, ranked by
3734/// distance to the archetype centroid.
3735#[derive(Clone, PartialEq, ::prost::Message)]
3736pub struct ExemplarSession {
3737 /// Session recording ID retrievable via ReplayService for the same
3738 /// org. Linkable from the admin regardless of originating platform.
3739 #[prost(string, tag="1")]
3740 pub session_id: ::prost::alloc::string::String,
3741 /// Quantile rank within the archetype: 25, 50, or 75. The writer
3742 /// emits at most one session per rank.
3743 #[prost(int32, tag="2")]
3744 pub rank: i32,
3745 /// L2 distance from the session's feature vector to the centroid.
3746 #[prost(double, tag="3")]
3747 pub distance: f64,
3748 /// Optional duration metadata for quick admin labelling.
3749 #[prost(int32, tag="4")]
3750 pub duration_seconds: i32,
3751 /// Optional platform identifier from the vocabulary
3752 /// {"ios", "android", "macos", "windows", "linux"}. The admin
3753 /// renders unknown values verbatim for forward compatibility.
3754 #[prost(string, tag="5")]
3755 pub platform: ::prost::alloc::string::String,
3756}
3757/// Per-screen dwell distribution within an archetype. Lets the admin
3758/// surface "this archetype lingers 8.2s on the Message Detail screen
3759/// vs 0.4s on the Inbox list".
3760#[derive(Clone, PartialEq, ::prost::Message)]
3761pub struct ScreenDwell {
3762 /// One entry per screen. Screens with fewer than k members in the
3763 /// archetype are dropped from the list (not marked as absent).
3764 #[prost(message, repeated, tag="1")]
3765 pub entries: ::prost::alloc::vec::Vec<ScreenDwellEntry>,
3766}
3767#[derive(Clone, PartialEq, ::prost::Message)]
3768pub struct ScreenDwellEntry {
3769 /// Stable screen identifier (e.g., "MessageDetail", "Inbox",
3770 /// "ProfileSettings"). Sourced from the same screen_name vocabulary
3771 /// used by heatmap_cells.
3772 #[prost(string, tag="1")]
3773 pub screen_name: ::prost::alloc::string::String,
3774 /// Median dwell time in seconds for this archetype on this screen.
3775 #[prost(double, tag="2")]
3776 pub median_seconds: f64,
3777 /// 75th-percentile dwell time in seconds.
3778 #[prost(double, tag="3")]
3779 pub p75_seconds: f64,
3780 /// Number of distinct sessions aggregated for this screen.
3781 #[prost(int32, tag="4")]
3782 pub session_count: i32,
3783}
3784/// End-to-end response latencies for members of one archetype, in
3785/// seconds. Each percentile is computed across all qualifying campaign
3786/// deliveries for the archetype's members within the rolling window.
3787#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3788pub struct ResponseTimeline {
3789 /// Time from `delivered_at` to `read_at`, in seconds.
3790 #[prost(message, optional, tag="1")]
3791 pub read_after_delivered: ::core::option::Option<LatencyPercentiles>,
3792 /// Time from `read_at` to `acknowledged_at`, in seconds. Only
3793 /// includes deliveries that were both read and acknowledged.
3794 #[prost(message, optional, tag="2")]
3795 pub ack_after_read: ::core::option::Option<LatencyPercentiles>,
3796 /// End-to-end time from `delivered_at` to `acknowledged_at`, in
3797 /// seconds. Only includes deliveries that were acknowledged.
3798 #[prost(message, optional, tag="3")]
3799 pub ack_after_delivered: ::core::option::Option<LatencyPercentiles>,
3800 /// Number of deliveries the timeline is computed over.
3801 #[prost(int32, tag="4")]
3802 pub delivery_count: i32,
3803}
3804/// Latency distribution stats. Values are in seconds.
3805#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3806pub struct LatencyPercentiles {
3807 #[prost(double, tag="1")]
3808 pub p50: f64,
3809 #[prost(double, tag="2")]
3810 pub p75: f64,
3811 #[prost(double, tag="3")]
3812 pub p95: f64,
3813}
3814/// A cohort-level prediction for campaign acknowledgment rate.
3815/// Never targets or scores individuals — always represents an audience aggregate.
3816#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3817pub struct CohortPrediction {
3818 /// Predicted ACK rate for the audience (0.0-1.0).
3819 #[prost(float, tag="1")]
3820 pub predicted_ack_rate: f32,
3821 /// Lower bound of the confidence interval.
3822 #[prost(float, tag="2")]
3823 pub confidence_low: f32,
3824 /// Upper bound of the confidence interval.
3825 #[prost(float, tag="3")]
3826 pub confidence_high: f32,
3827 /// Confidence level based on available data volume.
3828 #[prost(enumeration="ConfidenceLevel", tag="4")]
3829 pub confidence_level: i32,
3830 /// Number of anonymous data points used for this prediction.
3831 #[prost(int32, tag="5")]
3832 pub data_point_count: i32,
3833}
3834/// Advisory information for campaign configuration, combining predictions and archetypes.
3835#[derive(Clone, PartialEq, ::prost::Message)]
3836pub struct CampaignAdvisory {
3837 /// Cohort-level ACK prediction for the target audience.
3838 #[prost(message, optional, tag="1")]
3839 pub predicted_ack: ::core::option::Option<CohortPrediction>,
3840 /// Suggested escalation delay in minutes based on historical cohort patterns.
3841 /// 0 if insufficient data.
3842 #[prost(int32, tag="2")]
3843 pub suggested_escalation_delay_minutes: i32,
3844 /// Behavioral archetypes for the target audience.
3845 #[prost(message, repeated, tag="3")]
3846 pub archetypes: ::prost::alloc::vec::Vec<Archetype>,
3847}
3848/// Request to retrieve behavioral archetypes for a group.
3849#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3850pub struct GetGroupArchetypesRequest {
3851 /// ID of the group to query archetypes for. Required.
3852 #[prost(string, tag="1")]
3853 pub group_id: ::prost::alloc::string::String,
3854}
3855/// Response containing behavioral archetypes for a group.
3856#[derive(Clone, PartialEq, ::prost::Message)]
3857pub struct GetGroupArchetypesResponse {
3858 /// Behavioral archetypes for the group (empty if insufficient data).
3859 #[prost(message, repeated, tag="1")]
3860 pub archetypes: ::prost::alloc::vec::Vec<Archetype>,
3861 /// Number of anonymous feature vectors used for clustering.
3862 #[prost(int32, tag="2")]
3863 pub data_point_count: i32,
3864 /// Why `archetypes` looks the way it does. Lets the UI render a
3865 /// distinct empty-state affordance for "never trained" vs
3866 /// "below threshold" vs "no clusters" vs "ready". See PipelineState.
3867 #[prost(enumeration="PipelineState", tag="3")]
3868 pub pipeline_state: i32,
3869 /// Confidence in the returned archetypes, derived from available data
3870 /// volume. Always CONFIDENCE_LEVEL_LOW when provisional archetypes
3871 /// are returned — clients use this plus `Archetype.source` to render
3872 /// the low-confidence disclaimer.
3873 #[prost(enumeration="ConfidenceLevel", tag="4")]
3874 pub confidence_level: i32,
3875}
3876/// Request to predict cohort-level ACK rate for a campaign configuration.
3877#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3878pub struct PredictCampaignAckRequest {
3879 /// ID of the target audience group. Required.
3880 #[prost(string, tag="1")]
3881 pub group_id: ::prost::alloc::string::String,
3882 /// Template type (optional, for prediction refinement).
3883 #[prost(string, tag="2")]
3884 pub template_type: ::prost::alloc::string::String,
3885 /// Number of workflow steps (optional, for prediction refinement).
3886 #[prost(int32, tag="3")]
3887 pub workflow_step_count: i32,
3888}
3889/// Response containing a cohort-level ACK prediction.
3890#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3891pub struct PredictCampaignAckResponse {
3892 /// Cohort-level prediction.
3893 #[prost(message, optional, tag="1")]
3894 pub prediction: ::core::option::Option<CohortPrediction>,
3895}
3896/// Request for campaign configuration advisory.
3897#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3898pub struct GetCampaignAdvisoryRequest {
3899 /// ID of the target audience group. Required.
3900 #[prost(string, tag="1")]
3901 pub group_id: ::prost::alloc::string::String,
3902 /// Template ID (optional, for advisory context).
3903 #[prost(string, tag="2")]
3904 pub template_id: ::prost::alloc::string::String,
3905 /// Template version (optional).
3906 #[prost(int32, tag="3")]
3907 pub template_version: i32,
3908 /// Number of workflow steps (optional).
3909 #[prost(int32, tag="4")]
3910 pub workflow_step_count: i32,
3911}
3912/// Response containing campaign advisory information.
3913#[derive(Clone, PartialEq, ::prost::Message)]
3914pub struct GetCampaignAdvisoryResponse {
3915 /// Campaign advisory with prediction, suggested escalation, and archetypes.
3916 #[prost(message, optional, tag="1")]
3917 pub advisory: ::core::option::Option<CampaignAdvisory>,
3918}
3919/// Request to generate an AI narrative for a group's insights.
3920#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3921pub struct GetInsightNarrativeRequest {
3922 /// ID of the group to generate a narrative for. Required.
3923 #[prost(string, tag="1")]
3924 pub group_id: ::prost::alloc::string::String,
3925 /// Name of the prompt template to use (e.g., "campaign-advisory", "archetype-explanation").
3926 #[prost(string, tag="2")]
3927 pub prompt_name: ::prost::alloc::string::String,
3928}
3929/// Response containing an AI-generated narrative.
3930#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3931pub struct GetInsightNarrativeResponse {
3932 /// AI-generated narrative text (Markdown formatted).
3933 #[prost(string, tag="1")]
3934 pub narrative: ::prost::alloc::string::String,
3935 /// Timestamp when the narrative was generated.
3936 #[prost(message, optional, tag="2")]
3937 pub generated_at: ::core::option::Option<::prost_types::Timestamp>,
3938 /// Model identifier used for generation.
3939 #[prost(string, tag="3")]
3940 pub model_id: ::prost::alloc::string::String,
3941}
3942/// Request to manually trigger the ML training pipeline.
3943/// Empty — organization is extracted from the JWT.
3944#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3945pub struct TriggerMlPipelineRequest {
3946}
3947/// Response after triggering the ML pipeline.
3948#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3949pub struct TriggerMlPipelineResponse {
3950 /// Remaining manual retrains allowed this month.
3951 #[prost(int32, tag="1")]
3952 pub remaining_this_month: i32,
3953 /// Timestamp of the last successful training (null if never trained).
3954 #[prost(message, optional, tag="2")]
3955 pub last_trained_at: ::core::option::Option<::prost_types::Timestamp>,
3956}
3957/// Request to manually retrigger archetype clustering for a single group
3958/// without rerunning the full SageMaker training pipeline. Reuses the
3959/// already-deployed clustering model.
3960#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3961pub struct TriggerArchetypeClusteringRequest {
3962 /// Group to recluster. Org is extracted from the JWT.
3963 #[prost(string, tag="1")]
3964 pub group_id: ::prost::alloc::string::String,
3965}
3966/// Response after triggering archetype clustering for one group.
3967#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3968pub struct TriggerArchetypeClusteringResponse {
3969 /// Temporal workflow id — useful for client-side dedupe + operator
3970 /// debugging via the Temporal UI.
3971 #[prost(string, tag="1")]
3972 pub workflow_id: ::prost::alloc::string::String,
3973 /// Remaining manual retrains allowed this month. Shares the same
3974 /// monthly counter as TriggerMLPipeline (ml_manual_limit_monthly).
3975 #[prost(int32, tag="2")]
3976 pub remaining_this_month: i32,
3977 /// Timestamp of the last successful archetype clustering for this
3978 /// (org, group), null if never clustered.
3979 #[prost(message, optional, tag="3")]
3980 pub last_clustered_at: ::core::option::Option<::prost_types::Timestamp>,
3981}
3982/// Request to draft a campaign body for a given archetype using Bedrock.
3983/// Used by the Compass "Target this archetype in a new campaign" CTA to
3984/// pre-fill the campaign creation wizard's body field.
3985#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3986pub struct GenerateCampaignBodyDraftRequest {
3987 /// UUID of the source group whose archetype set the label belongs to.
3988 #[prost(string, tag="1")]
3989 pub group_id: ::prost::alloc::string::String,
3990 /// Stable archetype label, e.g. "Swift Acknowledger".
3991 #[prost(string, tag="2")]
3992 pub archetype_label: ::prost::alloc::string::String,
3993 /// Lane-recommended action copy passed through from the admin (e.g.
3994 /// "Simplify the call-to-action"). Used as a tone hint for the prompt.
3995 #[prost(string, tag="3")]
3996 pub lane_action: ::prost::alloc::string::String,
3997}
3998/// Response containing the generated draft body in Markdown.
3999#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4000pub struct GenerateCampaignBodyDraftResponse {
4001 /// Draft Markdown body, 3-5 sentences. Authored as if written for the
4002 /// recipient — does not mention the archetype name.
4003 #[prost(string, tag="1")]
4004 pub body_markdown: ::prost::alloc::string::String,
4005}
4006// ─── Enums ──────────────────────────────────────────────────────────────────
4007
4008/// Confidence level for cohort-level predictions, based on available data volume.
4009#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4010#[repr(i32)]
4011pub enum ConfidenceLevel {
4012 Unspecified = 0,
4013 /// Fewer than 50 campaigns — predictions based on heuristics/industry benchmarks.
4014 Low = 1,
4015 /// 50-200 campaigns — basic clustering available, wide confidence intervals.
4016 Medium = 2,
4017 /// 200+ campaigns — full ML pipeline, narrow confidence intervals.
4018 High = 3,
4019}
4020impl ConfidenceLevel {
4021 /// String value of the enum field names used in the ProtoBuf definition.
4022 ///
4023 /// The values are not transformed in any way and thus are considered stable
4024 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4025 pub fn as_str_name(&self) -> &'static str {
4026 match self {
4027 Self::Unspecified => "CONFIDENCE_LEVEL_UNSPECIFIED",
4028 Self::Low => "CONFIDENCE_LEVEL_LOW",
4029 Self::Medium => "CONFIDENCE_LEVEL_MEDIUM",
4030 Self::High => "CONFIDENCE_LEVEL_HIGH",
4031 }
4032 }
4033 /// Creates an enum from field names used in the ProtoBuf definition.
4034 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4035 match value {
4036 "CONFIDENCE_LEVEL_UNSPECIFIED" => Some(Self::Unspecified),
4037 "CONFIDENCE_LEVEL_LOW" => Some(Self::Low),
4038 "CONFIDENCE_LEVEL_MEDIUM" => Some(Self::Medium),
4039 "CONFIDENCE_LEVEL_HIGH" => Some(Self::High),
4040 _ => None,
4041 }
4042 }
4043}
4044/// Pipeline state for a group's archetypes. Lets the admin UI render
4045/// distinct empty-state affordances ("run clustering" vs "need N more
4046/// sessions" vs "pipeline ran but audience was too homogeneous") instead
4047/// of treating every empty archetype list the same. Populated by
4048/// InsightsService.GetGroupArchetypes.
4049#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4050#[repr(i32)]
4051pub enum PipelineState {
4052 Unspecified = 0,
4053 /// The ML pipeline has never fired for this org. Archetypes are
4054 /// empty because nothing ran, not because of data shape.
4055 NeverRun = 1,
4056 /// The pipeline ran but the group had fewer than the k-anonymization
4057 /// minimum feature vectors (50), so clustering was skipped. UI
4058 /// renders "keep running campaigns" affordance.
4059 BelowThreshold = 2,
4060 /// The pipeline ran with enough vectors but the clustering provider
4061 /// returned zero clusters — typically means the audience is too
4062 /// homogeneous to separate into distinct archetypes.
4063 NoClusters = 3,
4064 /// Archetypes are populated and ready to render.
4065 Ready = 4,
4066}
4067impl PipelineState {
4068 /// String value of the enum field names used in the ProtoBuf definition.
4069 ///
4070 /// The values are not transformed in any way and thus are considered stable
4071 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4072 pub fn as_str_name(&self) -> &'static str {
4073 match self {
4074 Self::Unspecified => "PIPELINE_STATE_UNSPECIFIED",
4075 Self::NeverRun => "PIPELINE_STATE_NEVER_RUN",
4076 Self::BelowThreshold => "PIPELINE_STATE_BELOW_THRESHOLD",
4077 Self::NoClusters => "PIPELINE_STATE_NO_CLUSTERS",
4078 Self::Ready => "PIPELINE_STATE_READY",
4079 }
4080 }
4081 /// Creates an enum from field names used in the ProtoBuf definition.
4082 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4083 match value {
4084 "PIPELINE_STATE_UNSPECIFIED" => Some(Self::Unspecified),
4085 "PIPELINE_STATE_NEVER_RUN" => Some(Self::NeverRun),
4086 "PIPELINE_STATE_BELOW_THRESHOLD" => Some(Self::BelowThreshold),
4087 "PIPELINE_STATE_NO_CLUSTERS" => Some(Self::NoClusters),
4088 "PIPELINE_STATE_READY" => Some(Self::Ready),
4089 _ => None,
4090 }
4091 }
4092}
4093/// Where an archetype came from. Lets clients distinguish trained ML
4094/// clustering output from low-confidence provisional output generated
4095/// for sandboxes and opted-in organizations before enough engagement
4096/// data exists. Clients MUST render a low-confidence disclaimer for
4097/// PROVISIONAL archetypes.
4098#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4099#[repr(i32)]
4100pub enum ArchetypeSource {
4101 Unspecified = 0,
4102 /// Produced by the trained ML clustering pipeline (k-anonymized,
4103 /// DP-noised behavioral feature vectors).
4104 Ml = 1,
4105 /// Rule-based provisional output derived from coarse delivery/read/
4106 /// ack activity (or a stable starter distribution for sandboxes with
4107 /// no activity). Low confidence, never written to the ML artifact
4108 /// path, and always superseded by ML output once available.
4109 Provisional = 2,
4110}
4111impl ArchetypeSource {
4112 /// String value of the enum field names used in the ProtoBuf definition.
4113 ///
4114 /// The values are not transformed in any way and thus are considered stable
4115 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4116 pub fn as_str_name(&self) -> &'static str {
4117 match self {
4118 Self::Unspecified => "ARCHETYPE_SOURCE_UNSPECIFIED",
4119 Self::Ml => "ARCHETYPE_SOURCE_ML",
4120 Self::Provisional => "ARCHETYPE_SOURCE_PROVISIONAL",
4121 }
4122 }
4123 /// Creates an enum from field names used in the ProtoBuf definition.
4124 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4125 match value {
4126 "ARCHETYPE_SOURCE_UNSPECIFIED" => Some(Self::Unspecified),
4127 "ARCHETYPE_SOURCE_ML" => Some(Self::Ml),
4128 "ARCHETYPE_SOURCE_PROVISIONAL" => Some(Self::Provisional),
4129 _ => None,
4130 }
4131 }
4132}
4133// ─── Messages ───────────────────────────────────────────────────────────────
4134
4135/// A single reachability registry row, returned by `GetReachability` and
4136/// `ListReachabilityForUser`. The plaintext identifier and envelope ciphertext
4137/// are NEVER returned over the wire — only metadata. The dispatch worker reads
4138/// the plaintext directly from the database and decrypts via KMS.
4139#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4140pub struct Reachability {
4141 /// Server-assigned row identifier (UUID).
4142 #[prost(string, tag="1")]
4143 pub id: ::prost::alloc::string::String,
4144 /// Organization that owns this reachability entry.
4145 #[prost(string, tag="2")]
4146 pub org_id: ::prost::alloc::string::String,
4147 /// User this reachability entry is for.
4148 #[prost(string, tag="3")]
4149 pub user_id: ::prost::alloc::string::String,
4150 /// Channel for which this entry stores a contact identifier.
4151 #[prost(enumeration="ChannelName", tag="4")]
4152 pub channel: i32,
4153 /// When the row was first written.
4154 #[prost(message, optional, tag="5")]
4155 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
4156 /// When the row was last upserted.
4157 #[prost(message, optional, tag="6")]
4158 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
4159 /// Optional AWS region identifier (e.g. "eu-west-1") this user's data must
4160 /// remain in for GDPR/residency reasons. Unset means "no constraint."
4161 /// Enforcement happens at dispatch time, not write time.
4162 #[prost(string, optional, tag="7")]
4163 pub region_constraint: ::core::option::Option<::prost::alloc::string::String>,
4164}
4165/// Per-(org, channel) region allowlist used by the dispatch worker to enforce
4166/// data-residency policy. An empty `allowed_regions` list means "no policy
4167/// configured" — NOT "no regions allowed."
4168#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4169pub struct RegionPolicy {
4170 #[prost(string, tag="1")]
4171 pub org_id: ::prost::alloc::string::String,
4172 #[prost(enumeration="ChannelName", tag="2")]
4173 pub channel: i32,
4174 /// AWS region identifiers (e.g. "eu-west-1", "us-east-1"). Empty list ==
4175 /// "no policy configured" — the dispatch worker SHALL NOT block on empty.
4176 #[prost(string, repeated, tag="3")]
4177 pub allowed_regions: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
4178 #[prost(message, optional, tag="4")]
4179 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
4180}
4181// ─── Enums ──────────────────────────────────────────────────────────────────
4182
4183/// Terminal status of a single dispatch attempt as returned by the worker-mode
4184/// `DispatchToChannel` RPC. Distinct from the richer `ChannelEventStatus` in
4185/// `channel_events.proto`, which models the audit-trail row for every state
4186/// transition (SENT → DELIVERED → OPENED → …). DispatchStatus is the immediate
4187/// outcome of one worker call.
4188#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4189#[repr(i32)]
4190pub enum DispatchStatus {
4191 /// Default value; should not be used explicitly.
4192 Unspecified = 0,
4193 /// The adapter accepted the message for delivery (provider returned success).
4194 Sent = 1,
4195 /// The adapter returned a terminal error (e.g. recipient blocked, domain not
4196 /// verified). Retries SHALL NOT be attempted; consult `failure_reason`.
4197 Failed = 2,
4198 /// An existing `(dispatch_id, SENT)` row was found by the idempotency guard
4199 /// before the adapter was called; the prior receipt was returned without a
4200 /// second provider call.
4201 Deduped = 3,
4202}
4203impl DispatchStatus {
4204 /// String value of the enum field names used in the ProtoBuf definition.
4205 ///
4206 /// The values are not transformed in any way and thus are considered stable
4207 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4208 pub fn as_str_name(&self) -> &'static str {
4209 match self {
4210 Self::Unspecified => "DISPATCH_STATUS_UNSPECIFIED",
4211 Self::Sent => "DISPATCH_STATUS_SENT",
4212 Self::Failed => "DISPATCH_STATUS_FAILED",
4213 Self::Deduped => "DISPATCH_STATUS_DEDUPED",
4214 }
4215 }
4216 /// Creates an enum from field names used in the ProtoBuf definition.
4217 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4218 match value {
4219 "DISPATCH_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
4220 "DISPATCH_STATUS_SENT" => Some(Self::Sent),
4221 "DISPATCH_STATUS_FAILED" => Some(Self::Failed),
4222 "DISPATCH_STATUS_DEDUPED" => Some(Self::Deduped),
4223 _ => None,
4224 }
4225 }
4226}
4227// ─── DispatchToChannel ──────────────────────────────────────────────────────
4228
4229/// Worker-mode entry point invoked by the Temporal worker for one recipient.
4230/// Idempotent on `dispatch_id`: if a `(dispatch_id, SENT)` row already exists
4231/// in `channel_dispatches`, the worker SHALL return DISPATCH_STATUS_DEDUPED
4232/// without re-invoking the channel adapter.
4233#[derive(Clone, PartialEq, ::prost::Message)]
4234pub struct DispatchToChannelRequest {
4235 /// Idempotency key. Must be stable across retries from pidgr-api side.
4236 #[prost(string, tag="1")]
4237 pub dispatch_id: ::prost::alloc::string::String,
4238 #[prost(string, tag="2")]
4239 pub org_id: ::prost::alloc::string::String,
4240 #[prost(string, tag="3")]
4241 pub user_id: ::prost::alloc::string::String,
4242 /// Which channel adapter to invoke (EMAIL is the Wave 1 implementation).
4243 #[prost(enumeration="ChannelName", tag="4")]
4244 pub channel: i32,
4245 /// Template to render before dispatch.
4246 #[prost(string, tag="5")]
4247 pub template_id: ::prost::alloc::string::String,
4248 /// Per-recipient template variables.
4249 #[prost(map="string, string", tag="6")]
4250 pub template_vars: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
4251 /// BCP-47 locale used to select the template translation.
4252 #[prost(string, tag="7")]
4253 pub locale: ::prost::alloc::string::String,
4254 /// Optional AWS region the worker MUST dispatch from (typically copied from
4255 /// the recipient's reachability row). Unset means "no constraint."
4256 #[prost(string, optional, tag="8")]
4257 pub region_constraint: ::core::option::Option<::prost::alloc::string::String>,
4258}
4259#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4260pub struct DispatchToChannelResponse {
4261 /// Echoes back the request's `dispatch_id`.
4262 #[prost(string, tag="1")]
4263 pub dispatch_id: ::prost::alloc::string::String,
4264 /// Terminal outcome of this call.
4265 #[prost(enumeration="DispatchStatus", tag="2")]
4266 pub status: i32,
4267 /// Human-readable failure reason; set only when `status` is
4268 /// DISPATCH_STATUS_FAILED.
4269 #[prost(string, optional, tag="3")]
4270 pub failure_reason: ::core::option::Option<::prost::alloc::string::String>,
4271}
4272// ─── UpsertReachability ─────────────────────────────────────────────────────
4273
4274/// Records a recipient identifier for a (user, channel) tuple. The plaintext
4275/// identifier is column-level KMS-encrypted on insert and never logged or
4276/// returned. The server computes the org-scoped HMAC lookup hash so opt-out
4277/// webhooks can find the row without decrypt.
4278#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4279pub struct UpsertReachabilityRequest {
4280 #[prost(string, tag="1")]
4281 pub org_id: ::prost::alloc::string::String,
4282 #[prost(string, tag="2")]
4283 pub user_id: ::prost::alloc::string::String,
4284 #[prost(enumeration="ChannelName", tag="3")]
4285 pub channel: i32,
4286 /// The plaintext identifier (email address, phone number, Slack user ID,
4287 /// Telegram chat ID, etc.). Encrypted at rest server-side. Servers MUST NOT
4288 /// log this field. Clients SHOULD treat this message as sensitive.
4289 #[prost(string, tag="4")]
4290 pub identifier_plaintext: ::prost::alloc::string::String,
4291 /// Optional AWS region this user's data must remain in (e.g. "eu-west-1").
4292 /// Recorded but NOT enforced at write time; enforcement is at dispatch.
4293 #[prost(string, optional, tag="5")]
4294 pub region_constraint: ::core::option::Option<::prost::alloc::string::String>,
4295}
4296#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4297pub struct UpsertReachabilityResponse {
4298 /// The metadata for the upserted row. Plaintext identifier and envelope
4299 /// ciphertext are intentionally absent.
4300 #[prost(message, optional, tag="1")]
4301 pub reachability: ::core::option::Option<Reachability>,
4302}
4303// ─── RemoveReachability ─────────────────────────────────────────────────────
4304
4305/// Idempotent removal. GDPR Recital 30 audit row is appended via internal-mTLS
4306/// BEFORE the registry row is deleted (see AuditService.Append). If no row
4307/// existed, `removed = false` and no audit row is emitted.
4308#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4309pub struct RemoveReachabilityRequest {
4310 #[prost(string, tag="1")]
4311 pub org_id: ::prost::alloc::string::String,
4312 #[prost(string, tag="2")]
4313 pub user_id: ::prost::alloc::string::String,
4314 #[prost(enumeration="ChannelName", tag="3")]
4315 pub channel: i32,
4316}
4317#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4318pub struct RemoveReachabilityResponse {
4319 /// True if a row was deleted. False if no row existed for the tuple
4320 /// (idempotent success).
4321 #[prost(bool, tag="1")]
4322 pub removed: bool,
4323}
4324// ─── GetReachability ────────────────────────────────────────────────────────
4325
4326/// Returns the reachability metadata for a single (user, channel) tuple.
4327/// Returns NOT_FOUND if no row exists.
4328#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4329pub struct GetReachabilityRequest {
4330 #[prost(string, tag="1")]
4331 pub org_id: ::prost::alloc::string::String,
4332 #[prost(string, tag="2")]
4333 pub user_id: ::prost::alloc::string::String,
4334 #[prost(enumeration="ChannelName", tag="3")]
4335 pub channel: i32,
4336}
4337#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4338pub struct GetReachabilityResponse {
4339 /// Plaintext identifier and envelope ciphertext are intentionally absent.
4340 #[prost(message, optional, tag="1")]
4341 pub reachability: ::core::option::Option<Reachability>,
4342}
4343// ─── ListReachabilityForUser ────────────────────────────────────────────────
4344
4345/// Returns one Reachability entry per channel configured for a (org, user)
4346/// pair. Used by the admin-side per-user matrix view. Plaintext identifiers
4347/// and envelope ciphertext are intentionally absent — the admin UI only needs
4348/// to know which channels are configured.
4349#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4350pub struct ListReachabilityForUserRequest {
4351 #[prost(string, tag="1")]
4352 pub org_id: ::prost::alloc::string::String,
4353 #[prost(string, tag="2")]
4354 pub user_id: ::prost::alloc::string::String,
4355}
4356#[derive(Clone, PartialEq, ::prost::Message)]
4357pub struct ListReachabilityForUserResponse {
4358 /// One entry per channel that has a row for the (org_id, user_id) pair.
4359 #[prost(message, repeated, tag="1")]
4360 pub reachabilities: ::prost::alloc::vec::Vec<Reachability>,
4361}
4362// ─── GetRegionPolicy / SetRegionPolicy ──────────────────────────────────────
4363
4364#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4365pub struct GetRegionPolicyRequest {
4366 #[prost(string, tag="1")]
4367 pub org_id: ::prost::alloc::string::String,
4368 #[prost(enumeration="ChannelName", tag="2")]
4369 pub channel: i32,
4370}
4371#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4372pub struct GetRegionPolicyResponse {
4373 /// Always populated. Empty `allowed_regions` means "no policy configured"
4374 /// — NOT "no regions allowed."
4375 #[prost(message, optional, tag="1")]
4376 pub policy: ::core::option::Option<RegionPolicy>,
4377}
4378/// Admin-only upsert. Empty `allowed_regions` clears the policy.
4379#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4380pub struct SetRegionPolicyRequest {
4381 #[prost(string, tag="1")]
4382 pub org_id: ::prost::alloc::string::String,
4383 #[prost(enumeration="ChannelName", tag="2")]
4384 pub channel: i32,
4385 /// AWS region identifiers (e.g. "eu-west-1"). Empty list == "no policy."
4386 #[prost(string, repeated, tag="3")]
4387 pub allowed_regions: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
4388}
4389#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4390pub struct SetRegionPolicyResponse {
4391 #[prost(message, optional, tag="1")]
4392 pub policy: ::core::option::Option<RegionPolicy>,
4393}
4394// ─── GetCostCapPolicy / SetCostCapPolicy ────────────────────────────────────
4395
4396/// Get the cost-cap state for the current calendar-month period (UTC). When
4397/// no row exists for `(org_id, channel, period_yyyymm)`, the server returns
4398/// the channel default cap from server config
4399/// (`COST_CAP_DEFAULT_${CHANNEL}_MICROS`) with `used_micros = 0`.
4400#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4401pub struct GetCostCapPolicyRequest {
4402 #[prost(string, tag="1")]
4403 pub org_id: ::prost::alloc::string::String,
4404 #[prost(enumeration="ChannelName", tag="2")]
4405 pub channel: i32,
4406}
4407#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4408pub struct GetCostCapPolicyResponse {
4409 #[prost(string, tag="1")]
4410 pub org_id: ::prost::alloc::string::String,
4411 #[prost(enumeration="ChannelName", tag="2")]
4412 pub channel: i32,
4413 /// Current period's cap in micros (1/1_000_000 of a USD).
4414 #[prost(int64, tag="3")]
4415 pub cap_micros: i64,
4416 /// Current period's accumulated spend in micros.
4417 #[prost(int64, tag="4")]
4418 pub used_micros: i64,
4419 /// Calendar-month period in integer YYYYMM form (e.g. 202605 for May 2026).
4420 #[prost(int32, tag="5")]
4421 pub period_yyyymm: i32,
4422}
4423/// Admin-only upsert of the cap for the current calendar-month period. Future
4424/// periods inherit the most recent SetCostCapPolicy value until the next call.
4425#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4426pub struct SetCostCapPolicyRequest {
4427 #[prost(string, tag="1")]
4428 pub org_id: ::prost::alloc::string::String,
4429 #[prost(enumeration="ChannelName", tag="2")]
4430 pub channel: i32,
4431 #[prost(int64, tag="3")]
4432 pub cap_micros: i64,
4433}
4434#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4435pub struct SetCostCapPolicyResponse {
4436 #[prost(string, tag="1")]
4437 pub org_id: ::prost::alloc::string::String,
4438 #[prost(enumeration="ChannelName", tag="2")]
4439 pub channel: i32,
4440 #[prost(int64, tag="3")]
4441 pub cap_micros: i64,
4442 #[prost(int64, tag="4")]
4443 pub used_micros: i64,
4444 #[prost(int32, tag="5")]
4445 pub period_yyyymm: i32,
4446}
4447// ─── GetOrgWebhookConfig / SetOrgWebhookConfig ──────────────────────────────
4448
4449/// Get the org's generic-webhook channel configuration. The shared secret is
4450/// write-only and never returned — `has_secret` reports whether one is set.
4451#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4452pub struct GetOrgWebhookConfigRequest {
4453 #[prost(string, tag="1")]
4454 pub org_id: ::prost::alloc::string::String,
4455}
4456#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4457pub struct GetOrgWebhookConfigResponse {
4458 #[prost(string, tag="1")]
4459 pub org_id: ::prost::alloc::string::String,
4460 /// Destination URL Pidgr POSTs notification events to. Empty when no
4461 /// configuration exists.
4462 #[prost(string, tag="2")]
4463 pub url: ::prost::alloc::string::String,
4464 /// Whether dispatch via the WEBHOOK channel is enabled for the org.
4465 #[prost(bool, tag="3")]
4466 pub enabled: bool,
4467 /// Whether a signing secret is currently configured. The secret itself is
4468 /// never returned.
4469 #[prost(bool, tag="4")]
4470 pub has_secret: bool,
4471 #[prost(message, optional, tag="5")]
4472 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
4473 #[prost(message, optional, tag="6")]
4474 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
4475}
4476/// Admin-only upsert of the org's generic-webhook configuration. The server
4477/// validates the URL (https-only, public addresses only) before persisting,
4478/// and envelope-encrypts the secret at rest. Setting a new `secret` rotates
4479/// it; leaving `secret` unset keeps the existing one.
4480#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4481pub struct SetOrgWebhookConfigRequest {
4482 #[prost(string, tag="1")]
4483 pub org_id: ::prost::alloc::string::String,
4484 /// Destination URL. Constraints: https scheme; non-private, non-loopback
4485 /// host. Validation failures return `invalid_argument`.
4486 #[prost(string, tag="2")]
4487 pub url: ::prost::alloc::string::String,
4488 #[prost(bool, tag="3")]
4489 pub enabled: bool,
4490 /// Shared secret used for the `X-Pidgr-Signature` HMAC-SHA256 header.
4491 /// Write-only. Unset keeps the current secret; set rotates it.
4492 /// Constraints: 16–256 bytes when set.
4493 #[prost(string, optional, tag="4")]
4494 pub secret: ::core::option::Option<::prost::alloc::string::String>,
4495}
4496#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4497pub struct SetOrgWebhookConfigResponse {
4498 #[prost(string, tag="1")]
4499 pub org_id: ::prost::alloc::string::String,
4500 #[prost(string, tag="2")]
4501 pub url: ::prost::alloc::string::String,
4502 #[prost(bool, tag="3")]
4503 pub enabled: bool,
4504 #[prost(bool, tag="4")]
4505 pub has_secret: bool,
4506 #[prost(message, optional, tag="5")]
4507 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
4508 #[prost(message, optional, tag="6")]
4509 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
4510}
4511// ─── CreateChannelConnectLink ───────────────────────────────────────────────
4512
4513/// Mints a short-lived, HMAC-signed opt-in link a user follows to bind a
4514/// third-party channel to their (org, user). Only follow-style channels are
4515/// accepted: CHANNEL_NAME_TELEGRAM (bot-follow), CHANNEL_NAME_SLACK (OAuth),
4516/// CHANNEL_NAME_LINE (follow-code). Any other channel is rejected server-side
4517/// with `invalid_argument`. Wraps the pidgr-api `internal/linktoken` minter.
4518#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4519pub struct CreateChannelConnectLinkRequest {
4520 #[prost(string, tag="1")]
4521 pub org_id: ::prost::alloc::string::String,
4522 /// Internal user UUID; resolved via UserResolver on the server. The minted
4523 /// token binds the resulting channel identifier to this (org, user).
4524 #[prost(string, tag="2")]
4525 pub user_id: ::prost::alloc::string::String,
4526 /// Channel to connect. Constraints: must be one of CHANNEL_NAME_TELEGRAM,
4527 /// CHANNEL_NAME_SLACK, CHANNEL_NAME_LINE. Other values return
4528 /// `invalid_argument`.
4529 #[prost(enumeration="ChannelName", tag="3")]
4530 pub channel: i32,
4531}
4532#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4533pub struct CreateChannelConnectLinkResponse {
4534 /// The deep link the client renders for the user to follow (e.g. a
4535 /// Telegram bot-follow URL, Slack OAuth authorize URL, or LINE follow URL).
4536 #[prost(string, tag="1")]
4537 pub connect_url: ::prost::alloc::string::String,
4538 /// The raw 64-char base64url opt-in token embedded in `connect_url`,
4539 /// surfaced separately so clients can render it as a QR code or copy
4540 /// button. Implementation detail — clients SHOULD NOT parse or mutate it.
4541 #[prost(string, tag="2")]
4542 pub token: ::prost::alloc::string::String,
4543 /// When the minted token expires. After this time the link no longer
4544 /// binds and the user must request a fresh one.
4545 #[prost(message, optional, tag="3")]
4546 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
4547}
4548// ─── Messages ───────────────────────────────────────────────────────────────
4549
4550/// A shareable invite link that allows users to self-join an organization.
4551/// Links carry a role assignment and optional usage/expiry constraints.
4552#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4553pub struct InviteLink {
4554 /// Unique identifier for the invite link.
4555 #[prost(string, tag="1")]
4556 pub id: ::prost::alloc::string::String,
4557 /// Cryptographically random base64url-encoded token (43 characters).
4558 #[prost(string, tag="2")]
4559 pub token: ::prost::alloc::string::String,
4560 /// ID of the role assigned to users who redeem this link.
4561 #[prost(string, tag="3")]
4562 pub role_id: ::prost::alloc::string::String,
4563 /// Maximum number of times this link can be redeemed.
4564 /// 0 means unlimited.
4565 #[prost(int32, tag="4")]
4566 pub max_uses: i32,
4567 /// Number of times this link has been redeemed.
4568 #[prost(int32, tag="5")]
4569 pub use_count: i32,
4570 /// When the link expires. Empty if no expiry.
4571 #[prost(message, optional, tag="6")]
4572 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
4573 /// When the link was revoked. Empty if not revoked.
4574 #[prost(message, optional, tag="7")]
4575 pub revoked_at: ::core::option::Option<::prost_types::Timestamp>,
4576 /// ID of the admin who created the link.
4577 #[prost(string, tag="8")]
4578 pub created_by: ::prost::alloc::string::String,
4579 /// When the link was created.
4580 #[prost(message, optional, tag="9")]
4581 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
4582 /// Data governance region assigned to users who redeem this link. Empty means inherit from org default.
4583 /// Valid values: EU, LATAM, BR, APAC, US.
4584 #[prost(string, tag="10")]
4585 pub data_governance_region: ::prost::alloc::string::String,
4586}
4587/// Request to create a new invite link for the organization.
4588#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4589pub struct CreateInviteLinkRequest {
4590 /// ID of the role to assign. Defaults to the organization's employee role if empty.
4591 #[prost(string, tag="1")]
4592 pub role_id: ::prost::alloc::string::String,
4593 /// Maximum number of redemptions. 0 means unlimited.
4594 #[prost(int32, tag="2")]
4595 pub max_uses: i32,
4596 /// Number of hours until the link expires. 0 means no expiry.
4597 /// Constraints: Valid range 0 to 8760 (1 year).
4598 #[prost(int32, tag="3")]
4599 pub expires_in_hours: i32,
4600 /// Optional data governance region. Users who redeem this link inherit this region. Empty means inherit from org default.
4601 /// Valid values: EU, LATAM, BR, APAC, US.
4602 #[prost(string, tag="4")]
4603 pub data_governance_region: ::prost::alloc::string::String,
4604}
4605/// Response after creating an invite link.
4606#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4607pub struct CreateInviteLinkResponse {
4608 /// The newly created invite link.
4609 #[prost(message, optional, tag="1")]
4610 pub invite_link: ::core::option::Option<InviteLink>,
4611 /// Full URL for sharing (e.g. "<https://app.pidgr.com/join?token=<TOKEN>">).
4612 #[prost(string, tag="2")]
4613 pub url: ::prost::alloc::string::String,
4614}
4615/// Request to list all invite links for the organization.
4616#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4617pub struct ListInviteLinksRequest {
4618}
4619/// Response containing all invite links for the organization.
4620#[derive(Clone, PartialEq, ::prost::Message)]
4621pub struct ListInviteLinksResponse {
4622 /// All invite links (active, expired, maxed-out, and revoked), ordered by creation date descending.
4623 #[prost(message, repeated, tag="1")]
4624 pub invite_links: ::prost::alloc::vec::Vec<InviteLink>,
4625}
4626/// Request to revoke an invite link.
4627#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4628pub struct RevokeInviteLinkRequest {
4629 /// ID of the invite link to revoke. Required.
4630 #[prost(string, tag="1")]
4631 pub invite_link_id: ::prost::alloc::string::String,
4632}
4633/// Response after revoking an invite link.
4634#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4635pub struct RevokeInviteLinkResponse {
4636}
4637/// Request to redeem an invite link (authenticated — email extracted from JWT).
4638#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4639pub struct RedeemInviteLinkRequest {
4640 /// The invite link token from the URL query parameter.
4641 #[prost(string, tag="1")]
4642 pub token: ::prost::alloc::string::String,
4643}
4644/// Response after redeeming an invite link.
4645#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4646pub struct RedeemInviteLinkResponse {
4647 /// Name of the organization the user was added to.
4648 #[prost(string, tag="1")]
4649 pub organization_name: ::prost::alloc::string::String,
4650}
4651/// Request to validate an invite link and provision a user account if needed (unauthenticated).
4652#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4653pub struct ValidateInviteLinkRequest {
4654 /// The invite link token from the URL query parameter.
4655 #[prost(string, tag="1")]
4656 pub token: ::prost::alloc::string::String,
4657 /// Email address of the user joining the organization.
4658 /// Constraints: Max length 254 characters (RFC 5321).
4659 #[prost(string, tag="2")]
4660 pub email: ::prost::alloc::string::String,
4661}
4662/// Response after validating an invite link.
4663#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4664pub struct ValidateInviteLinkResponse {
4665 /// Name of the organization the invite link belongs to.
4666 #[prost(string, tag="1")]
4667 pub organization_name: ::prost::alloc::string::String,
4668}
4669// ─── Messages ───────────────────────────────────────────────────────────────
4670
4671/// Request to invite a new user to the organization.
4672#[derive(Clone, PartialEq, ::prost::Message)]
4673pub struct InviteUserRequest {
4674 /// Email address to send the invitation to.
4675 /// Constraints: Max length 254 characters (RFC 5321).
4676 #[prost(string, tag="1")]
4677 pub email: ::prost::alloc::string::String,
4678 /// Display name for the invited user.
4679 /// Constraints: Max length 200 characters.
4680 #[prost(string, tag="2")]
4681 pub name: ::prost::alloc::string::String,
4682 /// ID of the role to assign. Defaults to the organization's employee role if empty.
4683 #[prost(string, tag="4")]
4684 pub role_id: ::prost::alloc::string::String,
4685 /// Optional profile attributes to pre-fill at invitation time.
4686 #[prost(message, optional, tag="5")]
4687 pub profile: ::core::option::Option<UserProfile>,
4688 /// Optional data governance region for the invited user. Empty means inherit from org default.
4689 /// Valid values: EU, LATAM, BR, APAC, US.
4690 #[prost(string, tag="6")]
4691 pub data_governance_region: ::prost::alloc::string::String,
4692}
4693/// Response after inviting a user.
4694#[derive(Clone, PartialEq, ::prost::Message)]
4695pub struct InviteUserResponse {
4696 /// The newly created user (status: INVITED).
4697 #[prost(message, optional, tag="1")]
4698 pub user: ::core::option::Option<User>,
4699}
4700/// Request to retrieve a user by ID.
4701#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4702pub struct GetUserRequest {
4703 /// ID of the user to retrieve.
4704 #[prost(string, tag="1")]
4705 pub user_id: ::prost::alloc::string::String,
4706}
4707/// Response containing the requested user.
4708#[derive(Clone, PartialEq, ::prost::Message)]
4709pub struct GetUserResponse {
4710 /// The requested user.
4711 #[prost(message, optional, tag="1")]
4712 pub user: ::core::option::Option<User>,
4713}
4714/// Request to list users in the organization with pagination.
4715#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4716pub struct ListUsersRequest {
4717 /// Pagination parameters.
4718 #[prost(message, optional, tag="1")]
4719 pub pagination: ::core::option::Option<Pagination>,
4720}
4721/// Response containing a page of users.
4722#[derive(Clone, PartialEq, ::prost::Message)]
4723pub struct ListUsersResponse {
4724 /// List of users in this page.
4725 #[prost(message, repeated, tag="1")]
4726 pub users: ::prost::alloc::vec::Vec<User>,
4727 /// Pagination metadata for fetching subsequent pages.
4728 #[prost(message, optional, tag="2")]
4729 pub pagination_meta: ::core::option::Option<PaginationMeta>,
4730}
4731/// Request to change a user's role within the organization.
4732#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4733pub struct UpdateUserRoleRequest {
4734 /// ID of the user whose role to update.
4735 #[prost(string, tag="1")]
4736 pub user_id: ::prost::alloc::string::String,
4737 /// ID of the new role to assign.
4738 #[prost(string, tag="2")]
4739 pub role_id: ::prost::alloc::string::String,
4740}
4741/// Response after updating a user's role.
4742#[derive(Clone, PartialEq, ::prost::Message)]
4743pub struct UpdateUserRoleResponse {
4744 /// The updated user with the new role.
4745 #[prost(message, optional, tag="1")]
4746 pub user: ::core::option::Option<User>,
4747}
4748/// Request to deactivate a user within the organization.
4749#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4750pub struct DeactivateUserRequest {
4751 /// ID of the user to deactivate.
4752 #[prost(string, tag="1")]
4753 pub user_id: ::prost::alloc::string::String,
4754}
4755/// Response after deactivating a user.
4756#[derive(Clone, PartialEq, ::prost::Message)]
4757pub struct DeactivateUserResponse {
4758 /// The deactivated user (status: DEACTIVATED).
4759 #[prost(message, optional, tag="1")]
4760 pub user: ::core::option::Option<User>,
4761}
4762/// Request to reactivate a deactivated user.
4763#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4764pub struct ReactivateUserRequest {
4765 /// ID of the user to reactivate.
4766 #[prost(string, tag="1")]
4767 pub user_id: ::prost::alloc::string::String,
4768}
4769/// Response after reactivating a user.
4770#[derive(Clone, PartialEq, ::prost::Message)]
4771pub struct ReactivateUserResponse {
4772 /// The reactivated user (status: INVITED).
4773 #[prost(message, optional, tag="1")]
4774 pub user: ::core::option::Option<User>,
4775}
4776/// Request to revoke an invitation for a user who has not yet registered.
4777#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4778pub struct RevokeInviteRequest {
4779 /// ID of the invited user to remove.
4780 /// Constraints: UUID format (36 characters).
4781 #[prost(string, tag="1")]
4782 pub user_id: ::prost::alloc::string::String,
4783}
4784/// Response after revoking an invitation. Empty on success.
4785#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4786pub struct RevokeInviteResponse {
4787}
4788/// Request to update a user's profile attributes.
4789#[derive(Clone, PartialEq, ::prost::Message)]
4790pub struct UpdateUserProfileRequest {
4791 /// ID of the user whose profile to update.
4792 /// Empty or matching the caller's own ID allows self-update without PERMISSION_MEMBERS_MANAGE.
4793 #[prost(string, tag="1")]
4794 pub user_id: ::prost::alloc::string::String,
4795 /// Profile attributes to set. All provided fields overwrite existing values.
4796 #[prost(message, optional, tag="2")]
4797 pub profile: ::core::option::Option<UserProfile>,
4798}
4799/// Response after updating a user's profile.
4800#[derive(Clone, PartialEq, ::prost::Message)]
4801pub struct UpdateUserProfileResponse {
4802 /// The updated user with the new profile.
4803 #[prost(message, optional, tag="1")]
4804 pub user: ::core::option::Option<User>,
4805}
4806/// Request to retrieve the caller's platform settings.
4807#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4808pub struct GetUserSettingsRequest {
4809}
4810/// Response containing the caller's platform settings.
4811#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4812pub struct GetUserSettingsResponse {
4813 /// Current settings. Fields at their default value indicate the platform default.
4814 #[prost(message, optional, tag="1")]
4815 pub settings: ::core::option::Option<UserSettings>,
4816}
4817/// Request to update the caller's platform settings.
4818#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4819pub struct UpdateUserSettingsRequest {
4820 /// Settings to update. Only fields with non-default (non-UNSPECIFIED) values
4821 /// are applied; default-valued fields are left unchanged.
4822 #[prost(message, optional, tag="1")]
4823 pub settings: ::core::option::Option<UserSettings>,
4824}
4825/// Response after updating the caller's platform settings.
4826#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4827pub struct UpdateUserSettingsResponse {
4828 /// The full settings after the update.
4829 #[prost(message, optional, tag="1")]
4830 pub settings: ::core::option::Option<UserSettings>,
4831}
4832/// Request to invite multiple users to the organization in a single call.
4833#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4834pub struct BulkInviteUsersRequest {
4835 /// Email addresses to invite.
4836 /// Constraints: Min 1, max 100 emails. Duplicates are deduplicated before processing.
4837 #[prost(string, repeated, tag="1")]
4838 pub emails: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
4839 /// ID of the role to assign. Defaults to the organization's employee role if empty.
4840 #[prost(string, tag="2")]
4841 pub role_id: ::prost::alloc::string::String,
4842}
4843/// Per-email result within a bulk invite operation.
4844#[derive(Clone, PartialEq, ::prost::Message)]
4845pub struct BulkInviteResult {
4846 /// The email address that was processed.
4847 #[prost(string, tag="1")]
4848 pub email: ::prost::alloc::string::String,
4849 /// Whether the invitation succeeded.
4850 #[prost(bool, tag="2")]
4851 pub success: bool,
4852 /// Error message if the invitation failed (e.g. "user already exists").
4853 /// Empty on success.
4854 #[prost(string, tag="3")]
4855 pub error: ::prost::alloc::string::String,
4856 /// The created user. Only set on success.
4857 #[prost(message, optional, tag="4")]
4858 pub user: ::core::option::Option<User>,
4859}
4860/// Response after bulk inviting users.
4861#[derive(Clone, PartialEq, ::prost::Message)]
4862pub struct BulkInviteUsersResponse {
4863 /// Per-email results in the same order as the deduplicated input.
4864 #[prost(message, repeated, tag="1")]
4865 pub results: ::prost::alloc::vec::Vec<BulkInviteResult>,
4866 /// Number of users successfully invited.
4867 #[prost(int32, tag="2")]
4868 pub invited_count: i32,
4869 /// Number of emails that failed.
4870 #[prost(int32, tag="3")]
4871 pub failed_count: i32,
4872}
4873/// Request to confirm passkey enrollment after client-side WebAuthn registration.
4874/// The server verifies that the caller has at least one registered WebAuthn
4875/// credential before setting the enrollment attribute.
4876#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4877pub struct ConfirmPasskeyEnrollmentRequest {
4878}
4879/// Response after confirming passkey enrollment.
4880#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4881pub struct ConfirmPasskeyEnrollmentResponse {
4882 /// Whether enrollment was confirmed and the user attribute was updated.
4883 #[prost(bool, tag="1")]
4884 pub confirmed: bool,
4885}
4886/// Request to update a user's data governance region.
4887#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4888pub struct UpdateUserRegionRequest {
4889 /// ID of the user whose region to update. Required.
4890 #[prost(string, tag="1")]
4891 pub user_id: ::prost::alloc::string::String,
4892 /// New governance region, or empty to inherit from org default.
4893 /// Valid values: EU, LATAM, BR, APAC, US.
4894 #[prost(string, tag="2")]
4895 pub data_governance_region: ::prost::alloc::string::String,
4896}
4897/// Response after updating a user's governance region.
4898#[derive(Clone, PartialEq, ::prost::Message)]
4899pub struct UpdateUserRegionResponse {
4900 /// The updated user.
4901 #[prost(message, optional, tag="1")]
4902 pub user: ::core::option::Option<User>,
4903 /// Temporal workflow ID for the region migration, if a migration was triggered.
4904 /// Empty if the region didn't actually change.
4905 #[prost(string, tag="2")]
4906 pub migration_workflow_id: ::prost::alloc::string::String,
4907}
4908// ─── Messages ───────────────────────────────────────────────────────────────
4909
4910/// A single non-retired pepper version. Returned by GetPeppers.
4911///
4912/// During a rotation overlap, multiple versions are returned — callers
4913/// (e.g. pidgr-integrations) compute lookup hashes under EVERY returned
4914/// version to write or match against `identifier_lookup_hash_v1` and
4915/// `identifier_lookup_hash_v2` on the reachability registry.
4916#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4917pub struct Pepper {
4918 /// Monotonically-increasing version number. Lower versions retire first.
4919 #[prost(int32, tag="1")]
4920 pub version: i32,
4921 /// Raw HMAC key material. Sensitive — callers MUST NOT log or persist
4922 /// this value to disk. In-memory caching keyed on (org_id, version) with
4923 /// a short TTL is permitted and expected.
4924 #[prost(bytes="vec", tag="2")]
4925 pub key_material: ::prost::alloc::vec::Vec<u8>,
4926}
4927/// Request to fetch the active (non-retired) peppers for one org/purpose.
4928///
4929/// Auth: internal-mTLS only. This RPC exposes raw cryptographic key material
4930/// and MUST NOT be reachable from the public ingress or from JWT-authenticated
4931/// clients. The server SHALL reject any caller whose mTLS identity is not on
4932/// the configured allowlist.
4933#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4934pub struct GetPeppersRequest {
4935 /// Organization whose peppers are requested.
4936 #[prost(string, tag="1")]
4937 pub org_id: ::prost::alloc::string::String,
4938 /// Purpose identifier scoping which key family to return. Use
4939 /// `"reachability_lookup"` for the pidgr-integrations registry lookup hash.
4940 #[prost(string, tag="2")]
4941 pub purpose: ::prost::alloc::string::String,
4942}
4943#[derive(Clone, PartialEq, ::prost::Message)]
4944pub struct GetPeppersResponse {
4945 /// All non-retired pepper versions for the (org_id, purpose) pair, in
4946 /// ascending version order. Typically exactly one entry; two during a
4947 /// rotation overlap window; zero only when no pepper has ever been
4948 /// generated for this (org, purpose).
4949 #[prost(message, repeated, tag="1")]
4950 pub peppers: ::prost::alloc::vec::Vec<Pepper>,
4951}
4952// ─── Messages ───────────────────────────────────────────────────────────────
4953
4954/// Maps an identity provider claim to a user profile field.
4955/// Used for automatic profile population when users authenticate via SSO/SAML.
4956#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4957pub struct SsoAttributeMapping {
4958 /// Claim name from the identity provider (e.g. "urn:oid:2.5.4.11", "given_name").
4959 /// Constraints: Max length 500 characters.
4960 #[prost(string, tag="1")]
4961 pub idp_claim: ::prost::alloc::string::String,
4962 /// Target UserProfile field name (e.g. "department", "first_name").
4963 /// For custom attributes, use "custom:" prefix (e.g. "custom:cost_center").
4964 /// Constraints: Max length 100 characters.
4965 #[prost(string, tag="2")]
4966 pub profile_field: ::prost::alloc::string::String,
4967}
4968/// An organization (tenant) in the Pidgr platform.
4969#[derive(Clone, PartialEq, ::prost::Message)]
4970pub struct Organization {
4971 /// Unique identifier for the organization.
4972 #[prost(string, tag="1")]
4973 pub id: ::prost::alloc::string::String,
4974 /// Organization display name.
4975 /// Constraints: Max length 200 characters.
4976 #[prost(string, tag="2")]
4977 pub name: ::prost::alloc::string::String,
4978 /// Default workflow used when campaigns don't specify one.
4979 #[prost(message, optional, tag="3")]
4980 pub default_workflow: ::core::option::Option<WorkflowDefinition>,
4981 /// Timestamp when the organization was created.
4982 #[prost(message, optional, tag="4")]
4983 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
4984 /// Industry vertical.
4985 #[prost(enumeration="Industry", tag="5")]
4986 pub industry: i32,
4987 /// Employee headcount range.
4988 #[prost(enumeration="CompanySize", tag="6")]
4989 pub company_size: i32,
4990 /// SSO identity provider claim-to-profile mappings.
4991 /// Empty when the organization does not use SSO.
4992 #[prost(message, repeated, tag="7")]
4993 pub sso_attribute_mappings: ::prost::alloc::vec::Vec<SsoAttributeMapping>,
4994 /// Default language for new users in this organization.
4995 /// Empty means no org default (users auto-detect from device/browser).
4996 /// Valid values: en, es, pt-BR, zh, ja.
4997 #[prost(string, tag="8")]
4998 pub default_locale: ::prost::alloc::string::String,
4999 /// Organization lifecycle type.
5000 #[prost(enumeration="OrgType", tag="9")]
5001 pub org_type: i32,
5002 /// Expiration time for sandbox organizations. Empty for standard orgs.
5003 #[prost(message, optional, tag="10")]
5004 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
5005 /// Data governance framework (EU, LATAM, BR, APAC, US).
5006 /// Determines legal framework, DPA template, and Bedrock endpoint routing.
5007 #[prost(string, tag="11")]
5008 pub data_governance_region: ::prost::alloc::string::String,
5009 /// AWS region for content storage (resolved from data_governance_region).
5010 /// e.g., "eu-west-1", "us-east-1".
5011 #[prost(string, tag="12")]
5012 pub data_content_region: ::prost::alloc::string::String,
5013 /// ─── ML pipeline settings ──────────────────────────────────────────────────
5014 /// Cold-start threshold: completed campaigns below this count trigger immediate
5015 /// retraining. At or above, the org is flagged for the weekly cron.
5016 /// Default 10, range 1-100.
5017 #[prost(int32, tag="13")]
5018 pub ml_retrain_cold_threshold: i32,
5019 /// Whether cancelled campaigns count toward the training counter. Default true.
5020 #[prost(bool, tag="14")]
5021 pub ml_cancelled_counts: bool,
5022 /// Monthly limit on manual retrain triggers. Default 3, range 0-10.
5023 #[prost(int32, tag="15")]
5024 pub ml_manual_limit_monthly: i32,
5025 /// Number of manual retrains used in the current month (resets monthly).
5026 #[prost(int32, tag="16")]
5027 pub ml_manual_retrains_used: i32,
5028 /// Whether the org is flagged for the next weekly cron run.
5029 #[prost(bool, tag="17")]
5030 pub ml_needs_retrain: bool,
5031 /// Campaigns completed since the last ML training run.
5032 #[prost(int32, tag="18")]
5033 pub campaigns_since_last_training: i32,
5034 /// Total campaigns completed across the organization lifetime.
5035 #[prost(int32, tag="19")]
5036 pub total_completed_campaigns: i32,
5037 /// Timestamp of the most recent successful ML training. Empty if never trained.
5038 #[prost(message, optional, tag="20")]
5039 pub last_ml_training_at: ::core::option::Option<::prost_types::Timestamp>,
5040 /// Controls whether aggregate stats (campaign recipient/ack/missed counts)
5041 /// include synthetic data. Unset = default by org type: sandbox orgs include,
5042 /// standard orgs exclude. Derived intelligence (ML, analytics, attestation
5043 /// evidence) always excludes synthetic regardless of this setting.
5044 #[prost(bool, optional, tag="21")]
5045 pub include_synthetic_in_aggregates: ::core::option::Option<bool>,
5046 /// Whether the organization has opted into provisional (rule-based,
5047 /// low-confidence) archetypes for groups that don't yet have trained
5048 /// ML archetypes. Only meaningful for ORG_TYPE_STANDARD — sandbox
5049 /// organizations are always eligible regardless of this setting.
5050 /// Default false: production analytics stay conservative.
5051 #[prost(bool, tag="22")]
5052 pub provisional_archetypes_enabled: bool,
5053}
5054/// Request to create a new organization.
5055/// JWT auth only — the authenticated caller becomes the initial admin. Additional
5056/// admins are added via CreateInviteLink after the org exists.
5057#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5058pub struct CreateOrganizationRequest {
5059 /// Name for the new organization.
5060 /// Constraints: Max length 200 characters.
5061 #[prost(string, tag="1")]
5062 pub name: ::prost::alloc::string::String,
5063 /// Industry vertical for the organization.
5064 #[prost(enumeration="Industry", tag="2")]
5065 pub industry: i32,
5066 /// Employee headcount range.
5067 #[prost(enumeration="CompanySize", tag="3")]
5068 pub company_size: i32,
5069 /// Access code required during early access.
5070 /// Format: PIDGR-XXXXXXXX (8 alphanumeric characters).
5071 #[prost(string, tag="4")]
5072 pub access_code: ::prost::alloc::string::String,
5073 /// Data governance framework. Defaults to "US" if omitted.
5074 /// Valid values: EU, LATAM, BR, APAC, US.
5075 #[prost(string, tag="5")]
5076 pub data_governance_region: ::prost::alloc::string::String,
5077 /// Optional bootstrap fixture to seed the organization with starter data.
5078 /// Empty string means the default fixture.
5079 #[prost(string, tag="6")]
5080 pub fixture_id: ::prost::alloc::string::String,
5081}
5082/// Response after creating an organization.
5083#[derive(Clone, PartialEq, ::prost::Message)]
5084pub struct CreateOrganizationResponse {
5085 /// The newly created organization.
5086 #[prost(message, optional, tag="1")]
5087 pub organization: ::core::option::Option<Organization>,
5088 /// The admin user created for the organization.
5089 #[prost(message, optional, tag="2")]
5090 pub admin_user: ::core::option::Option<User>,
5091}
5092/// Request to retrieve the organization for the authenticated user.
5093#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5094pub struct GetOrganizationRequest {
5095}
5096/// Response containing the organization.
5097#[derive(Clone, PartialEq, ::prost::Message)]
5098pub struct GetOrganizationResponse {
5099 /// The organization the authenticated user belongs to.
5100 #[prost(message, optional, tag="1")]
5101 pub organization: ::core::option::Option<Organization>,
5102}
5103/// Request to update organization settings.
5104#[derive(Clone, PartialEq, ::prost::Message)]
5105pub struct UpdateOrganizationRequest {
5106 /// New organization name. Empty string leaves unchanged.
5107 /// Constraints: Max length 200 characters.
5108 #[prost(string, tag="1")]
5109 pub name: ::prost::alloc::string::String,
5110 /// New default workflow definition. Null leaves unchanged.
5111 #[prost(message, optional, tag="2")]
5112 pub default_workflow: ::core::option::Option<WorkflowDefinition>,
5113 /// New industry vertical. UNSPECIFIED leaves unchanged.
5114 #[prost(enumeration="Industry", tag="3")]
5115 pub industry: i32,
5116 /// New employee headcount range. UNSPECIFIED leaves unchanged.
5117 #[prost(enumeration="CompanySize", tag="4")]
5118 pub company_size: i32,
5119 /// New default language for new users. Empty string leaves unchanged.
5120 /// Valid values: en, es, pt-BR, zh, ja.
5121 #[prost(string, tag="5")]
5122 pub default_locale: ::prost::alloc::string::String,
5123 /// New ML cold-start threshold. 0 leaves unchanged, otherwise must be in \[1, 100\].
5124 #[prost(int32, tag="6")]
5125 pub ml_retrain_cold_threshold: i32,
5126 /// New ML cancelled-counts flag. Uses google.protobuf.BoolValue-style semantics
5127 /// via optional to distinguish "not provided" from "set to false".
5128 #[prost(bool, optional, tag="7")]
5129 pub ml_cancelled_counts: ::core::option::Option<bool>,
5130 /// New ML monthly manual limit. Negative leaves unchanged, otherwise must be in \[0, 10\].
5131 /// Encoded as int32 with -1 meaning "leave unchanged".
5132 #[prost(int32, tag="8")]
5133 pub ml_manual_limit_monthly: i32,
5134 /// Set the synthetic-aggregates override; unset leaves it unchanged.
5135 #[prost(bool, optional, tag="9")]
5136 pub include_synthetic_in_aggregates: ::core::option::Option<bool>,
5137 /// New provisional-archetypes opt-in for standard organizations.
5138 /// Unset leaves unchanged. Rejected for sandbox organizations, which
5139 /// are always eligible automatically.
5140 #[prost(bool, optional, tag="10")]
5141 pub provisional_archetypes_enabled: ::core::option::Option<bool>,
5142}
5143/// Response after updating the organization.
5144#[derive(Clone, PartialEq, ::prost::Message)]
5145pub struct UpdateOrganizationResponse {
5146 /// The updated organization.
5147 #[prost(message, optional, tag="1")]
5148 pub organization: ::core::option::Option<Organization>,
5149}
5150/// Request to replace all SSO attribute mappings for the organization.
5151#[derive(Clone, PartialEq, ::prost::Message)]
5152pub struct UpdateSsoAttributeMappingsRequest {
5153 /// Complete list of SSO mappings (replaces all existing mappings).
5154 #[prost(message, repeated, tag="1")]
5155 pub sso_attribute_mappings: ::prost::alloc::vec::Vec<SsoAttributeMapping>,
5156}
5157/// Response after updating SSO attribute mappings.
5158#[derive(Clone, PartialEq, ::prost::Message)]
5159pub struct UpdateSsoAttributeMappingsResponse {
5160 /// The updated organization with the new SSO mappings.
5161 #[prost(message, optional, tag="1")]
5162 pub organization: ::core::option::Option<Organization>,
5163}
5164/// Request to rotate the analytics salt and optionally increase the bucket count.
5165#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5166pub struct RotateAnalyticsSaltRequest {
5167 /// New bucket count. Must be >= current bucket count. 0 means keep current.
5168 #[prost(int32, tag="1")]
5169 pub new_bucket_count: i32,
5170}
5171/// Response after rotating the analytics salt.
5172#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5173pub struct RotateAnalyticsSaltResponse {
5174 /// The new bucket count after rotation.
5175 #[prost(int32, tag="1")]
5176 pub bucket_count: i32,
5177}
5178/// Request to update the analytics epsilon (differential privacy parameter).
5179#[derive(Clone, Copy, PartialEq, ::prost::Message)]
5180pub struct UpdateAnalyticsEpsilonRequest {
5181 /// New epsilon value. Must be in range \[0.5, 5.0\].
5182 #[prost(float, tag="1")]
5183 pub epsilon: f32,
5184}
5185/// Response after updating the analytics epsilon.
5186#[derive(Clone, Copy, PartialEq, ::prost::Message)]
5187pub struct UpdateAnalyticsEpsilonResponse {
5188 /// The new epsilon value.
5189 #[prost(float, tag="1")]
5190 pub epsilon: f32,
5191}
5192/// Request to create a sandbox organization for testing.
5193#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5194pub struct CreateSandboxOrganizationRequest {
5195 /// Name for the sandbox organization.
5196 /// Constraints: Max length 200 characters.
5197 #[prost(string, tag="1")]
5198 pub name: ::prost::alloc::string::String,
5199 /// Required expiration time. Max 30 days from now for interactive callers;
5200 /// API-key callers may set shorter TTLs for ephemeral test sandboxes.
5201 #[prost(message, optional, tag="2")]
5202 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
5203 /// Data governance framework. Defaults to "US" if omitted.
5204 /// Valid values: EU, LATAM, BR, APAC, US.
5205 #[prost(string, tag="3")]
5206 pub data_governance_region: ::prost::alloc::string::String,
5207 /// Optional bootstrap fixture to seed the sandbox with starter data.
5208 /// Empty string means the default fixture.
5209 /// Must match an id returned by ListSandboxFixtures.
5210 #[prost(string, tag="4")]
5211 pub fixture_id: ::prost::alloc::string::String,
5212}
5213/// Response after creating a sandbox organization.
5214#[derive(Clone, PartialEq, ::prost::Message)]
5215pub struct CreateSandboxOrganizationResponse {
5216 /// The newly created sandbox organization (org_type: SANDBOX).
5217 #[prost(message, optional, tag="1")]
5218 pub organization: ::core::option::Option<Organization>,
5219 /// The admin user created for the sandbox.
5220 #[prost(message, optional, tag="2")]
5221 pub admin_user: ::core::option::Option<User>,
5222}
5223/// Request to delete a sandbox organization. Only callable for orgs with
5224/// org_type=SANDBOX. Allowed for super admins of the sandbox or the creator.
5225#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5226pub struct DeleteSandboxOrganizationRequest {
5227 /// ID of the sandbox organization to delete.
5228 #[prost(string, tag="1")]
5229 pub org_id: ::prost::alloc::string::String,
5230}
5231/// Response after requesting deletion. Deletion runs asynchronously via
5232/// the DeleteOrgWorkflow; a success response means the workflow started.
5233#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5234pub struct DeleteSandboxOrganizationResponse {
5235 /// ID of the Temporal workflow handling the deletion.
5236 #[prost(string, tag="1")]
5237 pub workflow_id: ::prost::alloc::string::String,
5238}
5239/// A bootstrap fixture that can be applied when creating a new organization.
5240#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5241pub struct SandboxFixture {
5242 /// Stable slug for referencing this fixture (e.g. "starter", "empty",
5243 /// "fintech", "sales"). Pass it back as the fixture_id on create.
5244 #[prost(string, tag="1")]
5245 pub id: ::prost::alloc::string::String,
5246 /// Display name for admin UI (e.g. "Starter").
5247 #[prost(string, tag="2")]
5248 pub name: ::prost::alloc::string::String,
5249 /// Description shown alongside the fixture option in the UI.
5250 #[prost(string, tag="3")]
5251 pub description: ::prost::alloc::string::String,
5252 /// Exactly one fixture has is_default=true. Clients that show a simple
5253 /// "seed initial data" control select this fixture's id by default.
5254 #[prost(bool, tag="4")]
5255 pub is_default: bool,
5256}
5257/// Request to list all bootstrap fixtures available for seeding.
5258/// No parameters — catalog is the same for all callers.
5259#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5260pub struct ListSandboxFixturesRequest {
5261}
5262/// Response containing the bootstrap fixture catalog.
5263#[derive(Clone, PartialEq, ::prost::Message)]
5264pub struct ListSandboxFixturesResponse {
5265 /// All registered fixtures, ordered by name.
5266 #[prost(message, repeated, tag="1")]
5267 pub fixtures: ::prost::alloc::vec::Vec<SandboxFixture>,
5268}
5269/// Request to list all organizations the authenticated user belongs to.
5270/// No parameters — user identity is extracted from the JWT sub claim.
5271#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5272pub struct ListUserOrganizationsRequest {
5273}
5274/// Response containing all organizations the authenticated user belongs to.
5275#[derive(Clone, PartialEq, ::prost::Message)]
5276pub struct ListUserOrganizationsResponse {
5277 /// Organizations the user belongs to, ordered by created_at ascending.
5278 /// Excludes expired sandbox organizations.
5279 #[prost(message, repeated, tag="1")]
5280 pub organizations: ::prost::alloc::vec::Vec<Organization>,
5281}
5282/// Request to list only the sandbox organizations the authenticated user
5283/// belongs to (i.e. orgs where org_type = SANDBOX, filtered from the full
5284/// membership set). No parameters — user identity is extracted from the JWT
5285/// sub claim.
5286#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5287pub struct ListUserSandboxesRequest {
5288}
5289/// Response containing the user's sandbox organizations.
5290#[derive(Clone, PartialEq, ::prost::Message)]
5291pub struct ListUserSandboxesResponse {
5292 /// Sandbox organizations the user belongs to, ordered by expires_at
5293 /// ascending (soonest-expiring first — matches the admin UI
5294 /// /organization/sandboxes ordering). Excludes already-expired sandboxes
5295 /// (those are pending cleanup by SandboxCleanupWorkflow).
5296 #[prost(message, repeated, tag="1")]
5297 pub sandboxes: ::prost::alloc::vec::Vec<Organization>,
5298}
5299/// A single org-level data-processing toggle with consent-trace metadata.
5300/// The metadata records who flipped the toggle last and when, so the admin
5301/// consent-trace UI can show a verifiable change trail.
5302#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5303pub struct OrgPrivacyToggle {
5304 /// Whether this category of processing is enabled for the organization.
5305 #[prost(bool, tag="1")]
5306 pub enabled: bool,
5307 /// Email of the admin who last changed this toggle.
5308 /// Empty if the toggle has never been changed from its default.
5309 #[prost(string, tag="2")]
5310 pub last_changed_by_email: ::prost::alloc::string::String,
5311 /// When this toggle was last changed.
5312 /// Empty if the toggle has never been changed from its default.
5313 #[prost(message, optional, tag="3")]
5314 pub last_changed_at: ::core::option::Option<::prost_types::Timestamp>,
5315}
5316/// Org-level data-processing settings (compliance consent surface).
5317/// Each toggle gates an entire category of processing for every user in
5318/// the organization.
5319#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5320pub struct OrgPrivacySettings {
5321 /// Gates ML archetype clustering and ACK predictions.
5322 #[prost(message, optional, tag="1")]
5323 pub ai_clustering: ::core::option::Option<OrgPrivacyToggle>,
5324 /// Gates behavioral analytics (session replay, heatmaps, dwell metrics).
5325 #[prost(message, optional, tag="2")]
5326 pub behavioral_analytics: ::core::option::Option<OrgPrivacyToggle>,
5327 /// Gates third-party notification channel dispatch (email, Slack, SMS, …).
5328 #[prost(message, optional, tag="3")]
5329 pub third_party_channels: ::core::option::Option<OrgPrivacyToggle>,
5330}
5331/// Request to retrieve the org-level privacy settings.
5332/// The organization is extracted from the JWT.
5333#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5334pub struct GetOrgPrivacySettingsRequest {
5335}
5336/// Response containing the org-level privacy settings with consent-trace
5337/// metadata for each toggle.
5338#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5339pub struct GetOrgPrivacySettingsResponse {
5340 /// The organization's current privacy settings.
5341 #[prost(message, optional, tag="1")]
5342 pub settings: ::core::option::Option<OrgPrivacySettings>,
5343}
5344/// Request to update org-level privacy settings. Only the provided fields
5345/// are changed; unset fields leave the corresponding toggle unchanged.
5346#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5347pub struct UpdateOrgPrivacySettingsRequest {
5348 /// Enable or disable ML archetype clustering and ACK predictions.
5349 /// Unset leaves unchanged.
5350 #[prost(bool, optional, tag="1")]
5351 pub ai_clustering_enabled: ::core::option::Option<bool>,
5352 /// Enable or disable behavioral analytics. Unset leaves unchanged.
5353 #[prost(bool, optional, tag="2")]
5354 pub behavioral_analytics_enabled: ::core::option::Option<bool>,
5355 /// Enable or disable third-party notification channels.
5356 /// Unset leaves unchanged.
5357 #[prost(bool, optional, tag="3")]
5358 pub third_party_channels_enabled: ::core::option::Option<bool>,
5359}
5360/// Response after updating org-level privacy settings.
5361#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5362pub struct UpdateOrgPrivacySettingsResponse {
5363 /// The organization's privacy settings after the update, with refreshed
5364 /// consent-trace metadata.
5365 #[prost(message, optional, tag="1")]
5366 pub settings: ::core::option::Option<OrgPrivacySettings>,
5367}
5368// ─── Enums ───────────────────────────────────────────────────────────────────
5369
5370/// Industry vertical for an organization.
5371#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
5372#[repr(i32)]
5373pub enum Industry {
5374 Unspecified = 0,
5375 Technology = 1,
5376 Finance = 2,
5377 Healthcare = 3,
5378 Education = 4,
5379 Retail = 5,
5380 Manufacturing = 6,
5381 Media = 7,
5382 Other = 8,
5383}
5384impl Industry {
5385 /// String value of the enum field names used in the ProtoBuf definition.
5386 ///
5387 /// The values are not transformed in any way and thus are considered stable
5388 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
5389 pub fn as_str_name(&self) -> &'static str {
5390 match self {
5391 Self::Unspecified => "INDUSTRY_UNSPECIFIED",
5392 Self::Technology => "INDUSTRY_TECHNOLOGY",
5393 Self::Finance => "INDUSTRY_FINANCE",
5394 Self::Healthcare => "INDUSTRY_HEALTHCARE",
5395 Self::Education => "INDUSTRY_EDUCATION",
5396 Self::Retail => "INDUSTRY_RETAIL",
5397 Self::Manufacturing => "INDUSTRY_MANUFACTURING",
5398 Self::Media => "INDUSTRY_MEDIA",
5399 Self::Other => "INDUSTRY_OTHER",
5400 }
5401 }
5402 /// Creates an enum from field names used in the ProtoBuf definition.
5403 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
5404 match value {
5405 "INDUSTRY_UNSPECIFIED" => Some(Self::Unspecified),
5406 "INDUSTRY_TECHNOLOGY" => Some(Self::Technology),
5407 "INDUSTRY_FINANCE" => Some(Self::Finance),
5408 "INDUSTRY_HEALTHCARE" => Some(Self::Healthcare),
5409 "INDUSTRY_EDUCATION" => Some(Self::Education),
5410 "INDUSTRY_RETAIL" => Some(Self::Retail),
5411 "INDUSTRY_MANUFACTURING" => Some(Self::Manufacturing),
5412 "INDUSTRY_MEDIA" => Some(Self::Media),
5413 "INDUSTRY_OTHER" => Some(Self::Other),
5414 _ => None,
5415 }
5416 }
5417}
5418/// Employee headcount range for an organization.
5419#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
5420#[repr(i32)]
5421pub enum CompanySize {
5422 Unspecified = 0,
5423 CompanySize1200 = 1,
5424 CompanySize200500 = 2,
5425 CompanySize5001000 = 3,
5426 CompanySize10005000 = 4,
5427 CompanySize5000Plus = 5,
5428}
5429impl CompanySize {
5430 /// String value of the enum field names used in the ProtoBuf definition.
5431 ///
5432 /// The values are not transformed in any way and thus are considered stable
5433 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
5434 pub fn as_str_name(&self) -> &'static str {
5435 match self {
5436 Self::Unspecified => "COMPANY_SIZE_UNSPECIFIED",
5437 Self::CompanySize1200 => "COMPANY_SIZE_1_200",
5438 Self::CompanySize200500 => "COMPANY_SIZE_200_500",
5439 Self::CompanySize5001000 => "COMPANY_SIZE_500_1000",
5440 Self::CompanySize10005000 => "COMPANY_SIZE_1000_5000",
5441 Self::CompanySize5000Plus => "COMPANY_SIZE_5000_PLUS",
5442 }
5443 }
5444 /// Creates an enum from field names used in the ProtoBuf definition.
5445 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
5446 match value {
5447 "COMPANY_SIZE_UNSPECIFIED" => Some(Self::Unspecified),
5448 "COMPANY_SIZE_1_200" => Some(Self::CompanySize1200),
5449 "COMPANY_SIZE_200_500" => Some(Self::CompanySize200500),
5450 "COMPANY_SIZE_500_1000" => Some(Self::CompanySize5001000),
5451 "COMPANY_SIZE_1000_5000" => Some(Self::CompanySize10005000),
5452 "COMPANY_SIZE_5000_PLUS" => Some(Self::CompanySize5000Plus),
5453 _ => None,
5454 }
5455 }
5456}
5457/// Classification of an organization's lifecycle type.
5458#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
5459#[repr(i32)]
5460pub enum OrgType {
5461 Unspecified = 0,
5462 Standard = 1,
5463 Sandbox = 2,
5464 /// Reserved for platform operations. At most one per deployment, seeded
5465 /// by migration. Cannot be created via CreateOrganization.
5466 Staff = 3,
5467}
5468impl OrgType {
5469 /// String value of the enum field names used in the ProtoBuf definition.
5470 ///
5471 /// The values are not transformed in any way and thus are considered stable
5472 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
5473 pub fn as_str_name(&self) -> &'static str {
5474 match self {
5475 Self::Unspecified => "ORG_TYPE_UNSPECIFIED",
5476 Self::Standard => "ORG_TYPE_STANDARD",
5477 Self::Sandbox => "ORG_TYPE_SANDBOX",
5478 Self::Staff => "ORG_TYPE_STAFF",
5479 }
5480 }
5481 /// Creates an enum from field names used in the ProtoBuf definition.
5482 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
5483 match value {
5484 "ORG_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
5485 "ORG_TYPE_STANDARD" => Some(Self::Standard),
5486 "ORG_TYPE_SANDBOX" => Some(Self::Sandbox),
5487 "ORG_TYPE_STAFF" => Some(Self::Staff),
5488 _ => None,
5489 }
5490 }
5491}
5492// ─── Messages ───────────────────────────────────────────────────────────────
5493
5494/// Per-user rendering context containing variable substitutions.
5495#[derive(Clone, PartialEq, ::prost::Message)]
5496pub struct UserRenderContext {
5497 /// ID of the user being rendered for.
5498 #[prost(string, tag="1")]
5499 pub user_id: ::prost::alloc::string::String,
5500 /// Variable name-value pairs to substitute into the template.
5501 /// Constraints: Max 100 entries. Key max length 100 characters, value max length 10000 characters.
5502 #[prost(map="string, string", tag="2")]
5503 pub variables: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
5504}
5505/// Request to render a template for a batch of users.
5506#[derive(Clone, PartialEq, ::prost::Message)]
5507pub struct RenderBatchRequest {
5508 /// ID of the template to render.
5509 #[prost(string, tag="1")]
5510 pub template_id: ::prost::alloc::string::String,
5511 /// Version of the template to render.
5512 #[prost(int32, tag="2")]
5513 pub version: i32,
5514 /// Per-user rendering contexts with variable substitutions.
5515 /// Constraints: Max 10000 users per batch.
5516 #[prost(message, repeated, tag="3")]
5517 pub users: ::prost::alloc::vec::Vec<UserRenderContext>,
5518}
5519/// Streamed response for each user's rendered message.
5520/// One response is emitted per user in the batch.
5521#[derive(Clone, PartialEq, ::prost::Message)]
5522pub struct RenderBatchResponse {
5523 /// ID of the user this result is for.
5524 #[prost(string, tag="1")]
5525 pub user_id: ::prost::alloc::string::String,
5526 /// The rendered message (set on success).
5527 #[prost(message, optional, tag="2")]
5528 pub message: ::core::option::Option<Message>,
5529 /// Error message if rendering failed for this user (empty on success).
5530 #[prost(string, tag="3")]
5531 pub error: ::prost::alloc::string::String,
5532}
5533// ─── Messages ───────────────────────────────────────────────────────────────
5534
5535/// A session recording summary from the analytics provider.
5536/// Anonymous: no user identifiers are included.
5537#[derive(Clone, PartialEq, ::prost::Message)]
5538pub struct SessionRecording {
5539 /// Recording ID from the analytics provider.
5540 #[prost(string, tag="1")]
5541 pub id: ::prost::alloc::string::String,
5542 /// Timestamp when the recording started.
5543 #[prost(message, optional, tag="2")]
5544 pub start_time: ::core::option::Option<::prost_types::Timestamp>,
5545 /// Timestamp when the recording ended.
5546 #[prost(message, optional, tag="3")]
5547 pub end_time: ::core::option::Option<::prost_types::Timestamp>,
5548 /// Duration of the recording in seconds.
5549 #[prost(int32, tag="4")]
5550 pub duration_seconds: i32,
5551 /// Activity score (0.0–1.0).
5552 #[prost(float, tag="5")]
5553 pub activity_score: f32,
5554}
5555/// Request to list session recordings.
5556#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5557pub struct ListSessionRecordingsRequest {
5558 /// Optional: filter recordings by campaign ID (mapped to analytics property filter).
5559 /// Constraints: UUID format (36 characters).
5560 #[prost(string, tag="1")]
5561 pub campaign_id: ::prost::alloc::string::String,
5562 /// Optional: start of the time range filter (inclusive).
5563 #[prost(message, optional, tag="2")]
5564 pub date_from: ::core::option::Option<::prost_types::Timestamp>,
5565 /// Optional: end of the time range filter (inclusive).
5566 #[prost(message, optional, tag="3")]
5567 pub date_to: ::core::option::Option<::prost_types::Timestamp>,
5568 /// Pagination parameters.
5569 #[prost(message, optional, tag="4")]
5570 pub pagination: ::core::option::Option<Pagination>,
5571}
5572/// Response containing a page of session recordings.
5573#[derive(Clone, PartialEq, ::prost::Message)]
5574pub struct ListSessionRecordingsResponse {
5575 /// List of session recordings in this page.
5576 #[prost(message, repeated, tag="1")]
5577 pub recordings: ::prost::alloc::vec::Vec<SessionRecording>,
5578 /// Pagination metadata for fetching subsequent pages.
5579 #[prost(message, optional, tag="2")]
5580 pub pagination_meta: ::core::option::Option<PaginationMeta>,
5581}
5582/// Request to fetch rrweb snapshot events for a recording.
5583#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5584pub struct GetSessionSnapshotsRequest {
5585 /// Recording ID from the analytics provider.
5586 /// Constraints: Max length 200 characters.
5587 #[prost(string, tag="1")]
5588 pub recording_id: ::prost::alloc::string::String,
5589}
5590/// Response containing rrweb snapshot events.
5591#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5592pub struct GetSessionSnapshotsResponse {
5593 /// JSON-encoded array of rrweb eventWithTime objects.
5594 /// Clients parse this JSON to feed into rrweb-player.
5595 #[prost(string, tag="1")]
5596 pub snapshot_data: ::prost::alloc::string::String,
5597}
5598// ─── Messages ───────────────────────────────────────────────────────────────
5599
5600/// Request to list all roles in the caller's organization.
5601#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5602pub struct ListRolesRequest {
5603}
5604/// Response containing the organization's roles.
5605#[derive(Clone, PartialEq, ::prost::Message)]
5606pub struct ListRolesResponse {
5607 /// All roles in the organization, including their permission sets.
5608 #[prost(message, repeated, tag="1")]
5609 pub roles: ::prost::alloc::vec::Vec<Role>,
5610}
5611/// Request to create a new role in the caller's organization.
5612#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5613pub struct CreateRoleRequest {
5614 /// Display name for the role (e.g. "Team Lead"). Required.
5615 /// A slug is auto-generated from the name.
5616 #[prost(string, tag="1")]
5617 pub name: ::prost::alloc::string::String,
5618 /// Initial permission set for the role.
5619 /// PERMISSION_UNSPECIFIED values are rejected.
5620 #[prost(enumeration="Permission", repeated, tag="2")]
5621 pub permissions: ::prost::alloc::vec::Vec<i32>,
5622}
5623/// Response after creating a role.
5624#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5625pub struct CreateRoleResponse {
5626 /// The newly created role with its generated slug and permission set.
5627 #[prost(message, optional, tag="1")]
5628 pub role: ::core::option::Option<Role>,
5629}
5630/// Request to update a role's name and/or permissions.
5631#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5632pub struct UpdateRoleRequest {
5633 /// ID of the role to update. Required.
5634 #[prost(string, tag="1")]
5635 pub role_id: ::prost::alloc::string::String,
5636 /// New display name. If empty, the name is not changed.
5637 #[prost(string, tag="2")]
5638 pub name: ::prost::alloc::string::String,
5639 /// New permission set (replaces existing permissions entirely).
5640 /// If empty, permissions are not changed.
5641 /// PERMISSION_UNSPECIFIED values are rejected.
5642 #[prost(enumeration="Permission", repeated, tag="3")]
5643 pub permissions: ::prost::alloc::vec::Vec<i32>,
5644}
5645/// Response after updating a role.
5646#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5647pub struct UpdateRoleResponse {
5648 /// The updated role.
5649 #[prost(message, optional, tag="1")]
5650 pub role: ::core::option::Option<Role>,
5651}
5652/// Request to delete a role.
5653#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5654pub struct DeleteRoleRequest {
5655 /// ID of the role to delete. Required.
5656 #[prost(string, tag="1")]
5657 pub role_id: ::prost::alloc::string::String,
5658}
5659/// Response after deleting a role.
5660#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5661pub struct DeleteRoleResponse {
5662}
5663// ─── Messages ───────────────────────────────────────────────────────────────
5664
5665/// Custom SAML attribute name overrides for identity providers that use
5666/// non-standard attribute names. When provided, these override the
5667/// auto-detected values from the metadata URL host.
5668#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5669pub struct SamlAttributeNames {
5670 /// SAML attribute name for the user's email address.
5671 #[prost(string, tag="1")]
5672 pub email: ::prost::alloc::string::String,
5673 /// SAML attribute name for the user's first name.
5674 #[prost(string, tag="2")]
5675 pub given_name: ::prost::alloc::string::String,
5676 /// SAML attribute name for the user's last name.
5677 #[prost(string, tag="3")]
5678 pub family_name: ::prost::alloc::string::String,
5679}
5680/// An SSO identity provider configured for an organization.
5681#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5682pub struct SsoProvider {
5683 /// Unique identifier for the provider.
5684 #[prost(string, tag="1")]
5685 pub id: ::prost::alloc::string::String,
5686 /// Email domain that triggers this SSO provider (e.g. "acme.com").
5687 /// Constraints: Max length 253 characters (RFC 1035).
5688 #[prost(string, tag="2")]
5689 pub domain: ::prost::alloc::string::String,
5690 /// Type of identity provider.
5691 #[prost(enumeration="SsoProviderType", tag="3")]
5692 pub r#type: i32,
5693 /// SAML metadata URL or OIDC discovery URL.
5694 /// Constraints: Max length 2048 characters. HTTPS required.
5695 #[prost(string, tag="4")]
5696 pub metadata_url: ::prost::alloc::string::String,
5697 /// Name of the identity provider (used for signInWithRedirect).
5698 /// Set by the API when the IdP is created.
5699 #[prost(string, tag="5")]
5700 pub idp_provider_name: ::prost::alloc::string::String,
5701 /// Timestamp when the provider was created.
5702 #[prost(message, optional, tag="6")]
5703 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
5704 /// Timestamp when the provider was last updated.
5705 #[prost(message, optional, tag="7")]
5706 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
5707 /// Optional custom SAML attribute name overrides.
5708 #[prost(message, optional, tag="8")]
5709 pub attribute_mapping: ::core::option::Option<SamlAttributeNames>,
5710}
5711/// Request to check if an email domain has SSO configured.
5712/// This RPC is pre-authentication — no JWT required.
5713#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5714pub struct CheckSsoByDomainRequest {
5715 /// Email address to check. The domain part is extracted.
5716 /// Constraints: Max length 254 characters (RFC 5321).
5717 #[prost(string, tag="1")]
5718 pub email: ::prost::alloc::string::String,
5719}
5720/// Response for SSO domain check.
5721#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5722pub struct CheckSsoByDomainResponse {
5723 /// Whether SSO is enabled for the email's domain.
5724 #[prost(bool, tag="1")]
5725 pub sso_enabled: bool,
5726 /// Identity provider name for signInWithRedirect.
5727 /// Empty if sso_enabled is false.
5728 #[prost(string, tag="2")]
5729 pub provider_name: ::prost::alloc::string::String,
5730}
5731/// Request to create an SSO provider for the organization.
5732#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5733pub struct CreateSsoProviderRequest {
5734 /// Email domain to associate (e.g. "acme.com").
5735 /// Constraints: Max length 253 characters (RFC 1035).
5736 #[prost(string, tag="1")]
5737 pub domain: ::prost::alloc::string::String,
5738 /// Type of identity provider.
5739 #[prost(enumeration="SsoProviderType", tag="2")]
5740 pub r#type: i32,
5741 /// SAML metadata URL or OIDC discovery URL.
5742 /// Constraints: Max length 2048 characters. HTTPS required.
5743 #[prost(string, tag="3")]
5744 pub metadata_url: ::prost::alloc::string::String,
5745 /// Optional custom SAML attribute name overrides.
5746 /// When omitted, attribute names are auto-detected from the metadata URL.
5747 #[prost(message, optional, tag="4")]
5748 pub attribute_mapping: ::core::option::Option<SamlAttributeNames>,
5749}
5750/// Response after creating an SSO provider.
5751#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5752pub struct CreateSsoProviderResponse {
5753 /// The newly created SSO provider.
5754 #[prost(message, optional, tag="1")]
5755 pub provider: ::core::option::Option<SsoProvider>,
5756}
5757/// Request to get the SSO provider for the organization.
5758/// Returns the provider if one is configured, or empty if not.
5759#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5760pub struct GetSsoProviderRequest {
5761}
5762/// Response containing the organization's SSO provider.
5763#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5764pub struct GetSsoProviderResponse {
5765 /// The organization's SSO provider, or null if not configured.
5766 #[prost(message, optional, tag="1")]
5767 pub provider: ::core::option::Option<SsoProvider>,
5768}
5769/// Request to delete the organization's SSO provider.
5770#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5771pub struct DeleteSsoProviderRequest {
5772 /// ID of the provider to delete.
5773 #[prost(string, tag="1")]
5774 pub provider_id: ::prost::alloc::string::String,
5775}
5776/// Response after deleting an SSO provider.
5777#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5778pub struct DeleteSsoProviderResponse {
5779}
5780// ─── Enums ──────────────────────────────────────────────────────────────────
5781
5782/// Type of SSO identity provider.
5783#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
5784#[repr(i32)]
5785pub enum SsoProviderType {
5786 /// Default value; not a valid type.
5787 Unspecified = 0,
5788 /// SAML 2.0 identity provider (e.g. Okta, Azure AD).
5789 Saml = 1,
5790 /// OpenID Connect identity provider (e.g. Google Workspace, Auth0).
5791 Oidc = 2,
5792}
5793impl SsoProviderType {
5794 /// String value of the enum field names used in the ProtoBuf definition.
5795 ///
5796 /// The values are not transformed in any way and thus are considered stable
5797 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
5798 pub fn as_str_name(&self) -> &'static str {
5799 match self {
5800 Self::Unspecified => "SSO_PROVIDER_TYPE_UNSPECIFIED",
5801 Self::Saml => "SSO_PROVIDER_TYPE_SAML",
5802 Self::Oidc => "SSO_PROVIDER_TYPE_OIDC",
5803 }
5804 }
5805 /// Creates an enum from field names used in the ProtoBuf definition.
5806 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
5807 match value {
5808 "SSO_PROVIDER_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
5809 "SSO_PROVIDER_TYPE_SAML" => Some(Self::Saml),
5810 "SSO_PROVIDER_TYPE_OIDC" => Some(Self::Oidc),
5811 _ => None,
5812 }
5813 }
5814}
5815// ─── Messages ───────────────────────────────────────────────────────────────
5816
5817/// An organizational unit within an organization (e.g. department, division).
5818/// Teams represent the organizational structure and can serve as sender identity
5819/// in campaigns.
5820#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5821pub struct Team {
5822 /// Unique identifier for the team.
5823 #[prost(string, tag="1")]
5824 pub id: ::prost::alloc::string::String,
5825 /// Human-readable display name (unique within the organization).
5826 /// Constraints: Max length 200 characters.
5827 #[prost(string, tag="2")]
5828 pub name: ::prost::alloc::string::String,
5829 /// Optional description of the team's purpose.
5830 /// Constraints: Max length 1000 characters.
5831 #[prost(string, tag="3")]
5832 pub description: ::prost::alloc::string::String,
5833 /// Number of users currently in the team.
5834 #[prost(int32, tag="4")]
5835 pub member_count: i32,
5836 /// Timestamp when the team was created.
5837 #[prost(message, optional, tag="5")]
5838 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
5839 /// Timestamp when the team was last updated.
5840 #[prost(message, optional, tag="6")]
5841 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
5842 /// Whether this is the organization's default team (cannot be deleted or renamed).
5843 #[prost(bool, tag="7")]
5844 pub is_default: bool,
5845 /// ID of the user who created this team. Empty for system-seeded defaults.
5846 #[prost(string, tag="8")]
5847 pub created_by: ::prost::alloc::string::String,
5848}
5849/// Request to create a new team.
5850#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5851pub struct CreateTeamRequest {
5852 /// Display name for the team. Required.
5853 /// Constraints: Max length 200 characters.
5854 #[prost(string, tag="1")]
5855 pub name: ::prost::alloc::string::String,
5856 /// Optional description.
5857 /// Constraints: Max length 1000 characters.
5858 #[prost(string, tag="2")]
5859 pub description: ::prost::alloc::string::String,
5860}
5861/// Response after creating a team.
5862#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5863pub struct CreateTeamResponse {
5864 /// The newly created team.
5865 #[prost(message, optional, tag="1")]
5866 pub team: ::core::option::Option<Team>,
5867}
5868/// Request to retrieve a team by ID.
5869#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5870pub struct GetTeamRequest {
5871 /// ID of the team to retrieve. Required.
5872 #[prost(string, tag="1")]
5873 pub team_id: ::prost::alloc::string::String,
5874}
5875/// Response containing the requested team.
5876#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5877pub struct GetTeamResponse {
5878 /// The requested team.
5879 #[prost(message, optional, tag="1")]
5880 pub team: ::core::option::Option<Team>,
5881}
5882/// Request to list teams in the organization with pagination.
5883#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5884pub struct ListTeamsRequest {
5885 /// Pagination parameters.
5886 #[prost(message, optional, tag="1")]
5887 pub pagination: ::core::option::Option<Pagination>,
5888}
5889/// Response containing a page of teams.
5890#[derive(Clone, PartialEq, ::prost::Message)]
5891pub struct ListTeamsResponse {
5892 /// Teams in this page.
5893 #[prost(message, repeated, tag="1")]
5894 pub teams: ::prost::alloc::vec::Vec<Team>,
5895 /// Pagination metadata for fetching subsequent pages.
5896 #[prost(message, optional, tag="2")]
5897 pub pagination_meta: ::core::option::Option<PaginationMeta>,
5898}
5899/// Request to update a team's name and/or description.
5900#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5901pub struct UpdateTeamRequest {
5902 /// ID of the team to update. Required.
5903 #[prost(string, tag="1")]
5904 pub team_id: ::prost::alloc::string::String,
5905 /// New display name. If empty, the name is not changed.
5906 /// Default teams cannot be renamed.
5907 /// Constraints: Max length 200 characters.
5908 #[prost(string, tag="2")]
5909 pub name: ::prost::alloc::string::String,
5910 /// New description. If empty, the description is not changed.
5911 /// Constraints: Max length 1000 characters.
5912 #[prost(string, tag="3")]
5913 pub description: ::prost::alloc::string::String,
5914}
5915/// Response after updating a team.
5916#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5917pub struct UpdateTeamResponse {
5918 /// The updated team.
5919 #[prost(message, optional, tag="1")]
5920 pub team: ::core::option::Option<Team>,
5921}
5922/// Request to delete a team.
5923#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5924pub struct DeleteTeamRequest {
5925 /// ID of the team to delete. Required.
5926 /// Default teams cannot be deleted.
5927 #[prost(string, tag="1")]
5928 pub team_id: ::prost::alloc::string::String,
5929}
5930/// Response after deleting a team.
5931#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5932pub struct DeleteTeamResponse {
5933}
5934/// Request to add users to a team.
5935#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5936pub struct AddTeamMembersRequest {
5937 /// ID of the team to add members to. Required.
5938 #[prost(string, tag="1")]
5939 pub team_id: ::prost::alloc::string::String,
5940 /// IDs of users to add. Must belong to the same organization.
5941 /// Adding an existing member is a no-op (idempotent).
5942 /// Constraints: Max 100 user IDs per request.
5943 #[prost(string, repeated, tag="2")]
5944 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
5945}
5946/// Response after adding team members.
5947#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5948pub struct AddTeamMembersResponse {
5949 /// The team with updated member_count.
5950 #[prost(message, optional, tag="1")]
5951 pub team: ::core::option::Option<Team>,
5952}
5953/// Request to remove users from a team.
5954#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5955pub struct RemoveTeamMembersRequest {
5956 /// ID of the team to remove members from. Required.
5957 #[prost(string, tag="1")]
5958 pub team_id: ::prost::alloc::string::String,
5959 /// IDs of users to remove. Removing a non-member is a no-op (idempotent).
5960 /// Constraints: Max 100 user IDs per request.
5961 #[prost(string, repeated, tag="2")]
5962 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
5963}
5964/// Response after removing team members.
5965#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5966pub struct RemoveTeamMembersResponse {
5967 /// The team with updated member_count.
5968 #[prost(message, optional, tag="1")]
5969 pub team: ::core::option::Option<Team>,
5970}
5971/// Request to list members of a team with pagination.
5972#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5973pub struct ListTeamMembersRequest {
5974 /// ID of the team whose members to list. Required.
5975 #[prost(string, tag="1")]
5976 pub team_id: ::prost::alloc::string::String,
5977 /// Pagination parameters.
5978 #[prost(message, optional, tag="2")]
5979 pub pagination: ::core::option::Option<Pagination>,
5980}
5981/// Response containing a page of team members.
5982#[derive(Clone, PartialEq, ::prost::Message)]
5983pub struct ListTeamMembersResponse {
5984 /// Users in this page.
5985 #[prost(message, repeated, tag="1")]
5986 pub users: ::prost::alloc::vec::Vec<User>,
5987 /// Pagination metadata for fetching subsequent pages.
5988 #[prost(message, optional, tag="2")]
5989 pub pagination_meta: ::core::option::Option<PaginationMeta>,
5990}
5991// ─── Messages ───────────────────────────────────────────────────────────────
5992
5993/// A variable placeholder within a template that gets substituted during rendering.
5994#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5995pub struct TemplateVariable {
5996 /// Variable name used in the template body (e.g. "employee_name").
5997 /// Constraints: Max length 100 characters.
5998 #[prost(string, tag="1")]
5999 pub name: ::prost::alloc::string::String,
6000 /// Human-readable description of what this variable represents.
6001 /// Constraints: Max length 500 characters.
6002 #[prost(string, tag="2")]
6003 pub description: ::prost::alloc::string::String,
6004 /// Whether this variable must be provided during rendering.
6005 #[prost(bool, tag="3")]
6006 pub required: bool,
6007 /// Where this variable's value comes from (profile attribute or campaign config).
6008 #[prost(enumeration="TemplateVariableSource", tag="4")]
6009 pub source: i32,
6010 /// Fallback value used when the source does not provide a value.
6011 /// Constraints: Max length 1000 characters.
6012 #[prost(string, tag="5")]
6013 pub default_value: ::prost::alloc::string::String,
6014 /// When true, this variable's rendered value is masked in session replay
6015 /// and heatmap screenshots. Org admin controls per variable.
6016 #[prost(bool, tag="6")]
6017 pub pii: bool,
6018}
6019/// A versioned message template with variable placeholders.
6020/// Templates are append-only — updates create new versions.
6021#[derive(Clone, PartialEq, ::prost::Message)]
6022pub struct Template {
6023 /// Unique identifier for the template.
6024 #[prost(string, tag="1")]
6025 pub id: ::prost::alloc::string::String,
6026 /// Human-readable template name (admin-facing label).
6027 /// Constraints: Max length 200 characters.
6028 #[prost(string, tag="2")]
6029 pub name: ::prost::alloc::string::String,
6030 /// Template body with {{variable}} placeholders for substitution.
6031 /// Constraints: Max length 50000 characters.
6032 #[prost(string, tag="3")]
6033 pub body: ::prost::alloc::string::String,
6034 /// Variables that can be substituted into the template body.
6035 #[prost(message, repeated, tag="4")]
6036 pub variables: ::prost::alloc::vec::Vec<TemplateVariable>,
6037 /// Version number (auto-incremented on each update).
6038 #[prost(int32, tag="5")]
6039 pub version: i32,
6040 /// Timestamp when this version was created.
6041 #[prost(message, optional, tag="6")]
6042 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
6043 /// Timestamp of the most recent update (same as created_at for the latest version).
6044 #[prost(message, optional, tag="7")]
6045 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
6046 /// User-facing title shown as the message subject to recipients.
6047 /// Serves as the default title; campaigns can override it.
6048 /// Constraints: Max length 200 characters.
6049 #[prost(string, tag="8")]
6050 pub title: ::prost::alloc::string::String,
6051 /// Content format of this template (markdown, rich, HTML).
6052 /// UNSPECIFIED is treated as MARKDOWN for backward compatibility.
6053 #[prost(enumeration="TemplateType", tag="9")]
6054 pub r#type: i32,
6055 /// Language of the template body content (e.g., "en", "es", "ja").
6056 /// Defaults to the org's default_locale, falling back to "en".
6057 /// Translations are created as locale variants of this source.
6058 #[prost(string, tag="10")]
6059 pub source_locale: ::prost::alloc::string::String,
6060}
6061/// A locale-specific translation of a template's title and body.
6062/// Translations are created per template version and go through a review workflow.
6063#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6064pub struct TemplateTranslation {
6065 /// Unique identifier for this translation.
6066 #[prost(string, tag="1")]
6067 pub id: ::prost::alloc::string::String,
6068 /// ID of the source template.
6069 #[prost(string, tag="2")]
6070 pub template_id: ::prost::alloc::string::String,
6071 /// Version of the source template this translation is for.
6072 #[prost(int32, tag="3")]
6073 pub version: i32,
6074 /// Target locale (e.g., "es", "pt-BR", "zh", "ja").
6075 #[prost(string, tag="4")]
6076 pub locale: ::prost::alloc::string::String,
6077 /// Translated title.
6078 /// Constraints: Max length 200 characters.
6079 #[prost(string, tag="5")]
6080 pub title: ::prost::alloc::string::String,
6081 /// Translated body content with {{variable}} placeholders preserved.
6082 /// Constraints: Max length 50000 characters.
6083 #[prost(string, tag="6")]
6084 pub body: ::prost::alloc::string::String,
6085 /// Current review status.
6086 #[prost(enumeration="TranslationStatus", tag="7")]
6087 pub status: i32,
6088 /// Who created this translation ("ai:bedrock", "ai:deepl", or user UUID).
6089 #[prost(string, tag="8")]
6090 pub translated_by: ::prost::alloc::string::String,
6091 /// User who approved the translation. Empty until approved.
6092 #[prost(string, tag="9")]
6093 pub reviewed_by: ::prost::alloc::string::String,
6094 /// When the translation was approved.
6095 #[prost(message, optional, tag="10")]
6096 pub reviewed_at: ::core::option::Option<::prost_types::Timestamp>,
6097 /// When the translation was created.
6098 #[prost(message, optional, tag="11")]
6099 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
6100}
6101/// Request to create a new template.
6102#[derive(Clone, PartialEq, ::prost::Message)]
6103pub struct CreateTemplateRequest {
6104 /// Human-readable template name (admin-facing label).
6105 /// Constraints: Max length 200 characters.
6106 #[prost(string, tag="1")]
6107 pub name: ::prost::alloc::string::String,
6108 /// Template body with {{variable}} placeholders.
6109 /// Constraints: Max length 50000 characters.
6110 #[prost(string, tag="2")]
6111 pub body: ::prost::alloc::string::String,
6112 /// Variables available for substitution in the body.
6113 #[prost(message, repeated, tag="3")]
6114 pub variables: ::prost::alloc::vec::Vec<TemplateVariable>,
6115 /// User-facing title shown as the message subject to recipients.
6116 /// Constraints: Max length 200 characters.
6117 #[prost(string, tag="4")]
6118 pub title: ::prost::alloc::string::String,
6119 /// Content format of the template. Defaults to MARKDOWN if unspecified.
6120 #[prost(enumeration="TemplateType", tag="5")]
6121 pub r#type: i32,
6122 /// Language of the template body content. Defaults to org's default_locale.
6123 /// Valid values: en, es, pt-BR, zh, ja.
6124 #[prost(string, tag="6")]
6125 pub source_locale: ::prost::alloc::string::String,
6126}
6127/// Response after creating a template.
6128#[derive(Clone, PartialEq, ::prost::Message)]
6129pub struct CreateTemplateResponse {
6130 /// The newly created template (version 1).
6131 #[prost(message, optional, tag="1")]
6132 pub template: ::core::option::Option<Template>,
6133}
6134/// Request to update a template, creating a new version.
6135#[derive(Clone, PartialEq, ::prost::Message)]
6136pub struct UpdateTemplateRequest {
6137 /// ID of the template to update.
6138 #[prost(string, tag="1")]
6139 pub template_id: ::prost::alloc::string::String,
6140 /// New template body with {{variable}} placeholders.
6141 /// Constraints: Max length 50000 characters.
6142 #[prost(string, tag="2")]
6143 pub body: ::prost::alloc::string::String,
6144 /// Updated variables for substitution.
6145 #[prost(message, repeated, tag="3")]
6146 pub variables: ::prost::alloc::vec::Vec<TemplateVariable>,
6147}
6148/// Response after updating a template.
6149#[derive(Clone, PartialEq, ::prost::Message)]
6150pub struct UpdateTemplateResponse {
6151 /// The updated template with incremented version number.
6152 #[prost(message, optional, tag="1")]
6153 pub template: ::core::option::Option<Template>,
6154}
6155/// Request to retrieve a specific template version.
6156#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6157pub struct GetTemplateRequest {
6158 /// ID of the template to retrieve.
6159 #[prost(string, tag="1")]
6160 pub template_id: ::prost::alloc::string::String,
6161 /// Version to retrieve. 0 returns the latest version.
6162 #[prost(int32, tag="2")]
6163 pub version: i32,
6164}
6165/// Response containing the requested template.
6166#[derive(Clone, PartialEq, ::prost::Message)]
6167pub struct GetTemplateResponse {
6168 /// The requested template.
6169 #[prost(message, optional, tag="1")]
6170 pub template: ::core::option::Option<Template>,
6171}
6172/// Request to list templates with pagination.
6173#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6174pub struct ListTemplatesRequest {
6175 /// Pagination parameters.
6176 #[prost(message, optional, tag="1")]
6177 pub pagination: ::core::option::Option<Pagination>,
6178 /// Filter by template type. UNSPECIFIED returns all templates.
6179 #[prost(enumeration="TemplateType", tag="2")]
6180 pub r#type: i32,
6181}
6182/// Response containing a page of templates.
6183#[derive(Clone, PartialEq, ::prost::Message)]
6184pub struct ListTemplatesResponse {
6185 /// List of templates in this page (latest version of each).
6186 #[prost(message, repeated, tag="1")]
6187 pub templates: ::prost::alloc::vec::Vec<Template>,
6188 /// Pagination metadata for fetching subsequent pages.
6189 #[prost(message, optional, tag="2")]
6190 pub pagination_meta: ::core::option::Option<PaginationMeta>,
6191}
6192/// Request to create a translation for a template.
6193#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6194pub struct CreateTemplateTranslationRequest {
6195 /// ID of the template to translate.
6196 #[prost(string, tag="1")]
6197 pub template_id: ::prost::alloc::string::String,
6198 /// Version of the template to translate.
6199 #[prost(int32, tag="2")]
6200 pub version: i32,
6201 /// Target locale.
6202 #[prost(string, tag="3")]
6203 pub locale: ::prost::alloc::string::String,
6204 /// Translated title.
6205 #[prost(string, tag="4")]
6206 pub title: ::prost::alloc::string::String,
6207 /// Translated body content.
6208 #[prost(string, tag="5")]
6209 pub body: ::prost::alloc::string::String,
6210 /// Who created this translation ("ai:bedrock" or user UUID).
6211 #[prost(string, tag="6")]
6212 pub translated_by: ::prost::alloc::string::String,
6213 /// Initial status (typically DRAFT or AI_TRANSLATED).
6214 #[prost(enumeration="TranslationStatus", tag="7")]
6215 pub status: i32,
6216}
6217/// Response after creating a template translation.
6218#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6219pub struct CreateTemplateTranslationResponse {
6220 /// The created translation.
6221 #[prost(message, optional, tag="1")]
6222 pub translation: ::core::option::Option<TemplateTranslation>,
6223}
6224/// Request to update an existing template translation.
6225#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6226pub struct UpdateTemplateTranslationRequest {
6227 /// ID of the translation to update.
6228 #[prost(string, tag="1")]
6229 pub translation_id: ::prost::alloc::string::String,
6230 /// Updated title. Empty leaves unchanged.
6231 #[prost(string, tag="2")]
6232 pub title: ::prost::alloc::string::String,
6233 /// Updated body. Empty leaves unchanged.
6234 #[prost(string, tag="3")]
6235 pub body: ::prost::alloc::string::String,
6236 /// Updated status.
6237 #[prost(enumeration="TranslationStatus", tag="4")]
6238 pub status: i32,
6239}
6240/// Response after updating a template translation.
6241#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6242pub struct UpdateTemplateTranslationResponse {
6243 /// The updated translation.
6244 #[prost(message, optional, tag="1")]
6245 pub translation: ::core::option::Option<TemplateTranslation>,
6246}
6247/// Request to list translations for a template version.
6248#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6249pub struct ListTemplateTranslationsRequest {
6250 /// ID of the template.
6251 #[prost(string, tag="1")]
6252 pub template_id: ::prost::alloc::string::String,
6253 /// Version of the template. 0 returns translations for the latest version.
6254 #[prost(int32, tag="2")]
6255 pub version: i32,
6256}
6257/// Response containing all translations for a template version.
6258#[derive(Clone, PartialEq, ::prost::Message)]
6259pub struct ListTemplateTranslationsResponse {
6260 /// Translations for the requested template version.
6261 #[prost(message, repeated, tag="1")]
6262 pub translations: ::prost::alloc::vec::Vec<TemplateTranslation>,
6263}
6264/// Request to approve a template translation.
6265#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6266pub struct ApproveTemplateTranslationRequest {
6267 /// ID of the translation to approve.
6268 #[prost(string, tag="1")]
6269 pub translation_id: ::prost::alloc::string::String,
6270}
6271/// Response after approving a template translation.
6272#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6273pub struct ApproveTemplateTranslationResponse {
6274 /// The approved translation (status: APPROVED, reviewed_by and reviewed_at set).
6275 #[prost(message, optional, tag="1")]
6276 pub translation: ::core::option::Option<TemplateTranslation>,
6277}
6278// ─── Enums ──────────────────────────────────────────────────────────────────
6279
6280/// Content format of a template, determining which editor and renderer to use.
6281#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6282#[repr(i32)]
6283pub enum TemplateType {
6284 /// Default value; treated as MARKDOWN for backward compatibility.
6285 Unspecified = 0,
6286 /// Markdown with {{variable}} placeholders.
6287 Markdown = 1,
6288 /// Rich text format (reserved for future use).
6289 Rich = 2,
6290 /// Raw HTML format (reserved for future use).
6291 Html = 3,
6292}
6293impl TemplateType {
6294 /// String value of the enum field names used in the ProtoBuf definition.
6295 ///
6296 /// The values are not transformed in any way and thus are considered stable
6297 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6298 pub fn as_str_name(&self) -> &'static str {
6299 match self {
6300 Self::Unspecified => "TEMPLATE_TYPE_UNSPECIFIED",
6301 Self::Markdown => "TEMPLATE_TYPE_MARKDOWN",
6302 Self::Rich => "TEMPLATE_TYPE_RICH",
6303 Self::Html => "TEMPLATE_TYPE_HTML",
6304 }
6305 }
6306 /// Creates an enum from field names used in the ProtoBuf definition.
6307 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6308 match value {
6309 "TEMPLATE_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
6310 "TEMPLATE_TYPE_MARKDOWN" => Some(Self::Markdown),
6311 "TEMPLATE_TYPE_RICH" => Some(Self::Rich),
6312 "TEMPLATE_TYPE_HTML" => Some(Self::Html),
6313 _ => None,
6314 }
6315 }
6316}
6317/// Source from which a template variable's value is resolved at render time.
6318#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6319#[repr(i32)]
6320pub enum TemplateVariableSource {
6321 /// Default value; treated as CUSTOM for backward compatibility.
6322 Unspecified = 0,
6323 /// Auto-resolved from the target user's profile attributes.
6324 Profile = 1,
6325 /// Provided manually in the campaign or workflow step configuration.
6326 Custom = 2,
6327}
6328impl TemplateVariableSource {
6329 /// String value of the enum field names used in the ProtoBuf definition.
6330 ///
6331 /// The values are not transformed in any way and thus are considered stable
6332 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6333 pub fn as_str_name(&self) -> &'static str {
6334 match self {
6335 Self::Unspecified => "TEMPLATE_VARIABLE_SOURCE_UNSPECIFIED",
6336 Self::Profile => "TEMPLATE_VARIABLE_SOURCE_PROFILE",
6337 Self::Custom => "TEMPLATE_VARIABLE_SOURCE_CUSTOM",
6338 }
6339 }
6340 /// Creates an enum from field names used in the ProtoBuf definition.
6341 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6342 match value {
6343 "TEMPLATE_VARIABLE_SOURCE_UNSPECIFIED" => Some(Self::Unspecified),
6344 "TEMPLATE_VARIABLE_SOURCE_PROFILE" => Some(Self::Profile),
6345 "TEMPLATE_VARIABLE_SOURCE_CUSTOM" => Some(Self::Custom),
6346 _ => None,
6347 }
6348 }
6349}
6350/// Review status of a template translation.
6351#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6352#[repr(i32)]
6353pub enum TranslationStatus {
6354 Unspecified = 0,
6355 /// Translation draft, not yet reviewed.
6356 Draft = 1,
6357 /// Translation generated by AI, pending human review.
6358 AiTranslated = 2,
6359 /// Translation is being reviewed by a human.
6360 InReview = 3,
6361 /// Translation has been approved for use.
6362 Approved = 4,
6363}
6364impl TranslationStatus {
6365 /// String value of the enum field names used in the ProtoBuf definition.
6366 ///
6367 /// The values are not transformed in any way and thus are considered stable
6368 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6369 pub fn as_str_name(&self) -> &'static str {
6370 match self {
6371 Self::Unspecified => "TRANSLATION_STATUS_UNSPECIFIED",
6372 Self::Draft => "TRANSLATION_STATUS_DRAFT",
6373 Self::AiTranslated => "TRANSLATION_STATUS_AI_TRANSLATED",
6374 Self::InReview => "TRANSLATION_STATUS_IN_REVIEW",
6375 Self::Approved => "TRANSLATION_STATUS_APPROVED",
6376 }
6377 }
6378 /// Creates an enum from field names used in the ProtoBuf definition.
6379 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6380 match value {
6381 "TRANSLATION_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
6382 "TRANSLATION_STATUS_DRAFT" => Some(Self::Draft),
6383 "TRANSLATION_STATUS_AI_TRANSLATED" => Some(Self::AiTranslated),
6384 "TRANSLATION_STATUS_IN_REVIEW" => Some(Self::InReview),
6385 "TRANSLATION_STATUS_APPROVED" => Some(Self::Approved),
6386 _ => None,
6387 }
6388 }
6389}
6390// ─── Messages ───────────────────────────────────────────────────────────────
6391
6392/// Decoded deeplink-token payload. Populated by ValidateDeeplinkToken
6393/// only when validation succeeds.
6394#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6395pub struct DeeplinkTokenPayload {
6396 /// Campaign UUID the deeplink targets. The native app uses this for the
6397 /// authenticated GetCampaign follow-up post-recipient-auth.
6398 #[prost(string, tag="1")]
6399 pub campaign_id: ::prost::alloc::string::String,
6400 /// Recipient UUID the token authorizes. The token does not authenticate
6401 /// the recipient (that's the auth flow's job); it authorizes "this
6402 /// deeplink path is for this recipient" so the native app can refuse
6403 /// to render a token whose embedded recipient mismatches the signed-in
6404 /// user.
6405 #[prost(string, tag="2")]
6406 pub recipient_user_id: ::prost::alloc::string::String,
6407 /// Step kind the deeplink targets — REMINDER vs ESCALATION. Lets the
6408 /// native app pick the right campaign-card variant before the auth
6409 /// gate.
6410 #[prost(enumeration="ChannelStepKind", tag="3")]
6411 pub step_kind: i32,
6412 /// Expiry the token carries. Validation rejects tokens past this time
6413 /// even if the signature checks out.
6414 #[prost(message, optional, tag="4")]
6415 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
6416}
6417#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6418pub struct SignDeeplinkTokenRequest {
6419 /// Campaign whose deeplink this token authorizes. Constraints: required,
6420 /// must be a UUID and exist within the caller's organization.
6421 #[prost(string, tag="1")]
6422 pub campaign_id: ::prost::alloc::string::String,
6423 /// Recipient the token authorizes. Constraints: required, must be a UUID
6424 /// and a member of the campaign's audience.
6425 #[prost(string, tag="2")]
6426 pub recipient_user_id: ::prost::alloc::string::String,
6427 /// Step kind the deeplink targets. Required.
6428 #[prost(enumeration="ChannelStepKind", tag="3")]
6429 pub step_kind: i32,
6430 /// Token lifetime in seconds from now. Constraints: required, must be
6431 /// in (0, 30 * 24 * 3600] (1 second to 30 days). 30 days matches the
6432 /// platform's outer bound on actionable campaign lifetimes; longer
6433 /// tokens are not signed.
6434 #[prost(int64, tag="4")]
6435 pub ttl_seconds: i64,
6436}
6437#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6438pub struct SignDeeplinkTokenResponse {
6439 /// The signed token, ready to URL-embed in
6440 /// links.pidgr.com/c/{short_code}?t={token}. Format: base64url-encoded
6441 /// payload (JSON) + base64url-encoded HMAC-SHA256 trailer, joined by
6442 /// a single dot. Implementation detail — clients SHOULD NOT parse or
6443 /// mutate the token; they pass it back to ValidateDeeplinkToken.
6444 #[prost(string, tag="1")]
6445 pub token: ::prost::alloc::string::String,
6446 /// The expiry the token carries. Echoed back so clients don't need to
6447 /// redo the time-math the caller passed in via ttl_seconds.
6448 #[prost(message, optional, tag="2")]
6449 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
6450 /// The platform key version used to sign. Clients MAY record for
6451 /// telemetry but SHOULD NOT branch logic on it — the platform manages
6452 /// overlap windows during rotation transparently.
6453 #[prost(int32, tag="3")]
6454 pub key_version: i32,
6455}
6456#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6457pub struct ValidateDeeplinkTokenRequest {
6458 /// The token bytes from the deeplink URL's `t` query parameter.
6459 /// Constraints: required, non-empty.
6460 #[prost(string, tag="1")]
6461 pub token: ::prost::alloc::string::String,
6462 /// Campaign UUID embedded in the URL path (translated from the
6463 /// short-code by the native app via CampaignService.GetCampaignByShortCode).
6464 /// Validation rejects when the token's embedded campaign_id does not
6465 /// match — defense against replay attacks that swap the short-code
6466 /// path component while reusing a signed token from a different
6467 /// campaign.
6468 #[prost(string, tag="2")]
6469 pub campaign_id: ::prost::alloc::string::String,
6470}
6471#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6472pub struct ValidateDeeplinkTokenResponse {
6473 /// True when signature + expiry both check out under any active or
6474 /// overlap-window key version.
6475 #[prost(bool, tag="1")]
6476 pub valid: bool,
6477 /// Reason validation failed. Set only when valid=false; UNSPECIFIED
6478 /// when valid=true. The native app uses this to drive UX (silent retry
6479 /// vs. "this link expired" message vs. "this link looks tampered").
6480 #[prost(enumeration="ValidationFailureReason", tag="2")]
6481 pub failure_reason: i32,
6482 /// Decoded payload. Populated only when valid=true. The native app
6483 /// SHOULD compare payload.recipient_user_id against the signed-in user
6484 /// and refuse to render the campaign card on mismatch.
6485 #[prost(message, optional, tag="3")]
6486 pub payload: ::core::option::Option<DeeplinkTokenPayload>,
6487}
6488// ─── Enums ──────────────────────────────────────────────────────────────────
6489
6490/// Reason a deeplink-token validation failed. Empty when valid=true.
6491#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6492#[repr(i32)]
6493pub enum ValidationFailureReason {
6494 Unspecified = 0,
6495 /// Token bytes parsed but the HMAC signature did not verify under any
6496 /// active or overlap-window key version.
6497 InvalidSignature = 1,
6498 /// Token signature verified but its embedded expiry has passed.
6499 Expired = 2,
6500 /// Signature would have verified, but the key version that signed the
6501 /// token is past the rotation overlap window and has been hard-deleted.
6502 /// This means the token is older than the platform's retention bound
6503 /// (rotation cadence + overlap window) — operationally equivalent to
6504 /// EXPIRED but distinguishable for telemetry.
6505 KeyRetired = 3,
6506 /// Token bytes could not be parsed at all (not base64url, wrong length,
6507 /// missing payload separator, etc.). Indicates a tampered or
6508 /// truncated URL.
6509 Malformed = 4,
6510}
6511impl ValidationFailureReason {
6512 /// String value of the enum field names used in the ProtoBuf definition.
6513 ///
6514 /// The values are not transformed in any way and thus are considered stable
6515 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6516 pub fn as_str_name(&self) -> &'static str {
6517 match self {
6518 Self::Unspecified => "VALIDATION_FAILURE_REASON_UNSPECIFIED",
6519 Self::InvalidSignature => "VALIDATION_FAILURE_REASON_INVALID_SIGNATURE",
6520 Self::Expired => "VALIDATION_FAILURE_REASON_EXPIRED",
6521 Self::KeyRetired => "VALIDATION_FAILURE_REASON_KEY_RETIRED",
6522 Self::Malformed => "VALIDATION_FAILURE_REASON_MALFORMED",
6523 }
6524 }
6525 /// Creates an enum from field names used in the ProtoBuf definition.
6526 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6527 match value {
6528 "VALIDATION_FAILURE_REASON_UNSPECIFIED" => Some(Self::Unspecified),
6529 "VALIDATION_FAILURE_REASON_INVALID_SIGNATURE" => Some(Self::InvalidSignature),
6530 "VALIDATION_FAILURE_REASON_EXPIRED" => Some(Self::Expired),
6531 "VALIDATION_FAILURE_REASON_KEY_RETIRED" => Some(Self::KeyRetired),
6532 "VALIDATION_FAILURE_REASON_MALFORMED" => Some(Self::Malformed),
6533 _ => None,
6534 }
6535 }
6536}
6537include!("pidgr.v1.tonic.rs");
6538// @@protoc_insertion_point(module)