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