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 /// Classification of this event: MANAGEMENT for principal-initiated actions
1631 /// on the organization's configuration or operation, SYSTEM for high-volume
1632 /// data-plane events emitted during processing. The server derives the class
1633 /// from the event type, so events are never unclassified.
1634 #[prost(enumeration="AuditEventClass", tag="11")]
1635 pub event_class: i32,
1636 /// Timestamp when the event was recorded.
1637 #[prost(message, optional, tag="10")]
1638 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
1639}
1640/// Request to list audit events with optional filters.
1641/// Auth: Requires JWT. Admin only.
1642#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1643pub struct ListAuditEventsRequest {
1644 /// Pagination token from a previous response.
1645 #[prost(string, tag="1")]
1646 pub page_token: ::prost::alloc::string::String,
1647 /// Maximum number of events to return.
1648 /// Constraints: Min 1, max 100. Default 50.
1649 #[prost(int32, tag="2")]
1650 pub page_size: i32,
1651 /// Optional filter: only return events of this type.
1652 #[prost(enumeration="AuditEventType", tag="3")]
1653 pub event_type: i32,
1654 /// Optional filter: only return events by this actor.
1655 /// Constraints: UUID format (36 characters).
1656 #[prost(string, tag="4")]
1657 pub actor_id: ::prost::alloc::string::String,
1658 /// Optional filter: events after this timestamp (inclusive).
1659 #[prost(message, optional, tag="5")]
1660 pub start_time: ::core::option::Option<::prost_types::Timestamp>,
1661 /// Optional filter: events before this timestamp (exclusive).
1662 #[prost(message, optional, tag="6")]
1663 pub end_time: ::core::option::Option<::prost_types::Timestamp>,
1664 /// Optional filter: only return events in these classes.
1665 /// Empty means no filtering — events of all classes are returned. Because
1666 /// classification is derived from the event type, a non-empty filter also
1667 /// covers events recorded before classification existed.
1668 #[prost(enumeration="AuditEventClass", repeated, tag="7")]
1669 pub event_classes: ::prost::alloc::vec::Vec<i32>,
1670}
1671/// Response containing a paginated list of audit events.
1672#[derive(Clone, PartialEq, ::prost::Message)]
1673pub struct ListAuditEventsResponse {
1674 /// Audit events matching the request filters.
1675 #[prost(message, repeated, tag="1")]
1676 pub events: ::prost::alloc::vec::Vec<AuditEvent>,
1677 /// Token for fetching the next page. Empty when no more events.
1678 #[prost(string, tag="2")]
1679 pub next_page_token: ::prost::alloc::string::String,
1680}
1681/// Request to export the audit trail to S3 in a specified format.
1682/// Auth: Requires JWT. Admin only.
1683#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1684pub struct ExportAuditTrailRequest {
1685 /// Export format.
1686 #[prost(enumeration="AuditExportFormat", tag="1")]
1687 pub format: i32,
1688 /// Optional: export events after this timestamp.
1689 #[prost(message, optional, tag="2")]
1690 pub start_time: ::core::option::Option<::prost_types::Timestamp>,
1691 /// Optional: export events before this timestamp.
1692 #[prost(message, optional, tag="3")]
1693 pub end_time: ::core::option::Option<::prost_types::Timestamp>,
1694}
1695/// Response containing the export download URL.
1696#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1697pub struct ExportAuditTrailResponse {
1698 /// Pre-signed S3 URL to download the exported audit trail.
1699 /// Only populated when status is COMPLETED.
1700 #[prost(string, tag="1")]
1701 pub export_url: ::prost::alloc::string::String,
1702 /// Current status of the export request.
1703 #[prost(enumeration="PrivacyRequestStatus", tag="2")]
1704 pub status: i32,
1705}
1706/// A persistent record of an audit trail export request.
1707#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1708pub struct AuditExport {
1709 /// Unique identifier.
1710 #[prost(string, tag="1")]
1711 pub id: ::prost::alloc::string::String,
1712 /// Export format (csv, json).
1713 #[prost(string, tag="2")]
1714 pub format: ::prost::alloc::string::String,
1715 /// Current status.
1716 #[prost(enumeration="PrivacyRequestStatus", tag="3")]
1717 pub status: i32,
1718 /// Pre-signed download URL. Only populated when status is COMPLETED.
1719 #[prost(string, tag="4")]
1720 pub result_url: ::prost::alloc::string::String,
1721 /// Error message if the export failed.
1722 #[prost(string, tag="5")]
1723 pub error_message: ::prost::alloc::string::String,
1724 /// Email of the admin who requested the export.
1725 #[prost(string, tag="6")]
1726 pub requested_by_email: ::prost::alloc::string::String,
1727 /// When the export was requested.
1728 #[prost(message, optional, tag="7")]
1729 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
1730 /// When the export completed (if applicable).
1731 #[prost(message, optional, tag="8")]
1732 pub completed_at: ::core::option::Option<::prost_types::Timestamp>,
1733}
1734/// Request to list audit export history.
1735/// Auth: Requires JWT. Admin only.
1736#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
1737pub struct ListAuditExportsRequest {
1738}
1739/// Response containing the list of audit exports.
1740#[derive(Clone, PartialEq, ::prost::Message)]
1741pub struct ListAuditExportsResponse {
1742 /// Audit export records, newest first.
1743 #[prost(message, repeated, tag="1")]
1744 pub exports: ::prost::alloc::vec::Vec<AuditExport>,
1745}
1746/// Request to append a single audit event from an internal service.
1747///
1748/// Auth: INTERNAL-mTLS ONLY. Unlike the read-side RPCs which authenticate
1749/// via Cognito JWT and infer `org_id` from the caller's claim, this RPC is
1750/// invoked by sibling services (e.g. pidgr-integrations) over the internal
1751/// mTLS mesh and therefore carries `org_id` in the request payload. The
1752/// server MUST reject any caller presenting only a JWT.
1753#[derive(Clone, PartialEq, ::prost::Message)]
1754pub struct AppendRequest {
1755 /// String form of the event type. Sibling services use a stable string
1756 /// identifier (e.g. "REACHABILITY_UPSERT", "REACHABILITY_REMOVE") so a
1757 /// new event type does not require a coordinated proto release across
1758 /// every internal service before it can be recorded. The audit server
1759 /// is responsible for mapping the string into its internal taxonomy.
1760 #[prost(string, tag="1")]
1761 pub event_type: ::prost::alloc::string::String,
1762 /// Organization in which the event occurred. UUID.
1763 #[prost(string, tag="2")]
1764 pub org_id: ::prost::alloc::string::String,
1765 /// User the audit event is about, if applicable. UUID. Unset when the
1766 /// event is not subject-bound (e.g. an org-wide policy change).
1767 #[prost(string, optional, tag="3")]
1768 pub subject_user_id: ::core::option::Option<::prost::alloc::string::String>,
1769 /// Actor who initiated the action, if any. UUID. Unset for system-initiated
1770 /// or sibling-service-initiated events.
1771 #[prost(string, optional, tag="4")]
1772 pub actor_id: ::core::option::Option<::prost::alloc::string::String>,
1773 /// Structured event-specific payload. Used in lieu of the rigid
1774 /// `map<string, string> metadata` on `AuditEvent` so sibling services
1775 /// can record nested objects (e.g. a `prefetch_signals` block) without
1776 /// string-encoding every value. Servers SHOULD redact PII before persist
1777 /// and MUST NOT log this field at INFO or above. Sensitive cryptographic
1778 /// material (plaintext identifiers, envelope ciphertext, raw HMAC keys)
1779 /// MUST NOT be placed here.
1780 #[prost(message, optional, tag="5")]
1781 pub details: ::core::option::Option<::prost_types::Struct>,
1782}
1783#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
1784pub struct AppendResponse {
1785 /// Server-assigned audit event identifier (UUID).
1786 #[prost(string, tag="1")]
1787 pub event_id: ::prost::alloc::string::String,
1788}
1789// ─── Enums ──────────────────────────────────────────────────────────────────
1790
1791/// Type of auditable platform action.
1792#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
1793#[repr(i32)]
1794pub enum AuditEventType {
1795 /// Default value; should not be used explicitly.
1796 Unspecified = 0,
1797 /// ── Campaign lifecycle ───────────────────────────────────────────────────
1798 /// A campaign was created.
1799 CampaignCreated = 1,
1800 /// A message was sent to a recipient.
1801 MessageSent = 2,
1802 /// A message was opened by a recipient.
1803 MessageOpened = 3,
1804 /// A recipient acknowledged a campaign.
1805 AckRegistered = 4,
1806 /// An escalation was triggered by the workflow.
1807 EscalationExecuted = 5,
1808 /// A campaign was started.
1809 CampaignStarted = 12,
1810 /// A campaign was cancelled.
1811 CampaignCancelled = 13,
1812 /// A campaign was updated.
1813 CampaignUpdated = 14,
1814 /// ── User lifecycle ───────────────────────────────────────────────────────
1815 /// A user was invited to the organization.
1816 UserInvited = 6,
1817 /// A user was deactivated.
1818 UserDeactivated = 7,
1819 /// A user was reactivated.
1820 UserReactivated = 15,
1821 /// A user's role was changed (assigned to a different role).
1822 RoleChanged = 10,
1823 /// A user's invite was revoked.
1824 InviteRevoked = 16,
1825 /// A user's profile was updated.
1826 ProfileUpdated = 17,
1827 /// A user's settings were updated.
1828 SettingsUpdated = 18,
1829 /// A user enrolled a passkey.
1830 PasskeyEnrolled = 19,
1831 /// ── GDPR / Privacy ──────────────────────────────────────────────────────
1832 /// A data export was requested (GDPR Art. 15).
1833 DataExportRequested = 8,
1834 /// A data deletion was requested (GDPR Art. 17).
1835 DataDeletionRequested = 9,
1836 /// User data was rectified (GDPR Art. 16).
1837 DataRectified = 20,
1838 /// Data processing was restricted (GDPR Art. 18).
1839 ProcessingRestricted = 21,
1840 /// A scheduled deletion was cancelled.
1841 DeletionCancelled = 22,
1842 /// An immediate deletion was executed.
1843 DeletionImmediate = 23,
1844 /// ── Organization / SSO ───────────────────────────────────────────────────
1845 /// An SSO provider was configured.
1846 SsoConfigured = 11,
1847 /// An SSO provider was created.
1848 SsoProviderCreated = 24,
1849 /// An SSO provider was deleted.
1850 SsoProviderDeleted = 25,
1851 /// Organization settings were updated.
1852 OrgUpdated = 26,
1853 /// ── Roles ────────────────────────────────────────────────────────────────
1854 /// A role was created.
1855 RoleCreated = 27,
1856 /// A role's name or permissions were updated.
1857 RoleUpdated = 28,
1858 /// A role was deleted.
1859 RoleDeleted = 29,
1860 /// ── Templates ────────────────────────────────────────────────────────────
1861 /// A template was created.
1862 TemplateCreated = 30,
1863 /// A template was updated.
1864 TemplateUpdated = 31,
1865 /// ── API Keys ─────────────────────────────────────────────────────────────
1866 /// An API key was created.
1867 ApiKeyCreated = 32,
1868 /// An API key was revoked.
1869 ApiKeyRevoked = 33,
1870 /// ── Invite Links ─────────────────────────────────────────────────────────
1871 /// An invite link was created.
1872 InviteLinkCreated = 34,
1873 /// An invite link was revoked.
1874 InviteLinkRevoked = 35,
1875 /// ── Groups ───────────────────────────────────────────────────────────────
1876 /// A group was created.
1877 GroupCreated = 36,
1878 /// A group was updated.
1879 GroupUpdated = 37,
1880 /// A group was deleted.
1881 GroupDeleted = 38,
1882 /// Members were added to a group.
1883 GroupMembersAdded = 39,
1884 /// Members were removed from a group.
1885 GroupMembersRemoved = 40,
1886 /// ── Teams ────────────────────────────────────────────────────────────────
1887 /// A team was created.
1888 TeamCreated = 41,
1889 /// A team was updated.
1890 TeamUpdated = 42,
1891 /// A team was deleted.
1892 TeamDeleted = 43,
1893 /// Members were added to a team.
1894 TeamMembersAdded = 44,
1895 /// Members were removed from a team.
1896 TeamMembersRemoved = 45,
1897 /// ── SCIM Provisioning ───────────────────────────────────────────────────
1898 /// A user was provisioned via SCIM.
1899 ScimUserProvisioned = 46,
1900 /// A user was deprovisioned via SCIM.
1901 ScimUserDeprovisioned = 47,
1902 /// A user was updated via SCIM.
1903 ScimUserUpdated = 48,
1904 /// ── Translations ────────────────────────────────────────────────────────
1905 /// A template translation was created.
1906 TranslationCreated = 49,
1907 /// A template translation was approved.
1908 TranslationApproved = 50,
1909 /// ── Sandbox Orgs ────────────────────────────────────────────────────────
1910 /// A sandbox organization was created.
1911 SandboxCreated = 51,
1912 /// A sandbox organization expired and was deleted.
1913 SandboxExpired = 52,
1914 /// ── AI/Insights ─────────────────────────────────────────────────────────
1915 /// An AI prediction was served and logged (EU AI Act Art. 12).
1916 AiPredictionLogged = 53,
1917 /// The ML pipeline (archetype clustering + enrichment) was manually triggered.
1918 MlPipelineTriggered = 54,
1919 /// Per-group archetype clustering was manually triggered.
1920 ArchetypeClusteringTriggered = 55,
1921 /// ── Org lifecycle ───────────────────────────────────────────────────────
1922 /// An organization was created.
1923 OrgCreated = 56,
1924 /// An organization was deleted (sandbox cleanup or manual deletion).
1925 OrgDeleted = 57,
1926 /// ── Reachability registry (pidgr-integrations) ──────────────────────────
1927 /// A reachability identifier (email, phone, Slack ID, etc.) was upserted.
1928 /// GDPR-relevant per Chikorita audit classification.
1929 ReachabilityUpsert = 58,
1930 /// A reachability identifier was removed. GDPR Art. 17 "right to erasure"
1931 /// event; written BEFORE the registry row is deleted per Recital 30.
1932 ReachabilityRemove = 59,
1933 /// ── KMS envelope encryption ─────────────────────────────────────────────
1934 /// A payload was envelope-encrypted with a KMS-managed key.
1935 KmsEncrypt = 60,
1936 /// A payload was decrypted with a KMS-managed key.
1937 KmsDecrypt = 61,
1938}
1939impl AuditEventType {
1940 /// String value of the enum field names used in the ProtoBuf definition.
1941 ///
1942 /// The values are not transformed in any way and thus are considered stable
1943 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
1944 pub fn as_str_name(&self) -> &'static str {
1945 match self {
1946 Self::Unspecified => "AUDIT_EVENT_TYPE_UNSPECIFIED",
1947 Self::CampaignCreated => "AUDIT_EVENT_TYPE_CAMPAIGN_CREATED",
1948 Self::MessageSent => "AUDIT_EVENT_TYPE_MESSAGE_SENT",
1949 Self::MessageOpened => "AUDIT_EVENT_TYPE_MESSAGE_OPENED",
1950 Self::AckRegistered => "AUDIT_EVENT_TYPE_ACK_REGISTERED",
1951 Self::EscalationExecuted => "AUDIT_EVENT_TYPE_ESCALATION_EXECUTED",
1952 Self::CampaignStarted => "AUDIT_EVENT_TYPE_CAMPAIGN_STARTED",
1953 Self::CampaignCancelled => "AUDIT_EVENT_TYPE_CAMPAIGN_CANCELLED",
1954 Self::CampaignUpdated => "AUDIT_EVENT_TYPE_CAMPAIGN_UPDATED",
1955 Self::UserInvited => "AUDIT_EVENT_TYPE_USER_INVITED",
1956 Self::UserDeactivated => "AUDIT_EVENT_TYPE_USER_DEACTIVATED",
1957 Self::UserReactivated => "AUDIT_EVENT_TYPE_USER_REACTIVATED",
1958 Self::RoleChanged => "AUDIT_EVENT_TYPE_ROLE_CHANGED",
1959 Self::InviteRevoked => "AUDIT_EVENT_TYPE_INVITE_REVOKED",
1960 Self::ProfileUpdated => "AUDIT_EVENT_TYPE_PROFILE_UPDATED",
1961 Self::SettingsUpdated => "AUDIT_EVENT_TYPE_SETTINGS_UPDATED",
1962 Self::PasskeyEnrolled => "AUDIT_EVENT_TYPE_PASSKEY_ENROLLED",
1963 Self::DataExportRequested => "AUDIT_EVENT_TYPE_DATA_EXPORT_REQUESTED",
1964 Self::DataDeletionRequested => "AUDIT_EVENT_TYPE_DATA_DELETION_REQUESTED",
1965 Self::DataRectified => "AUDIT_EVENT_TYPE_DATA_RECTIFIED",
1966 Self::ProcessingRestricted => "AUDIT_EVENT_TYPE_PROCESSING_RESTRICTED",
1967 Self::DeletionCancelled => "AUDIT_EVENT_TYPE_DELETION_CANCELLED",
1968 Self::DeletionImmediate => "AUDIT_EVENT_TYPE_DELETION_IMMEDIATE",
1969 Self::SsoConfigured => "AUDIT_EVENT_TYPE_SSO_CONFIGURED",
1970 Self::SsoProviderCreated => "AUDIT_EVENT_TYPE_SSO_PROVIDER_CREATED",
1971 Self::SsoProviderDeleted => "AUDIT_EVENT_TYPE_SSO_PROVIDER_DELETED",
1972 Self::OrgUpdated => "AUDIT_EVENT_TYPE_ORG_UPDATED",
1973 Self::RoleCreated => "AUDIT_EVENT_TYPE_ROLE_CREATED",
1974 Self::RoleUpdated => "AUDIT_EVENT_TYPE_ROLE_UPDATED",
1975 Self::RoleDeleted => "AUDIT_EVENT_TYPE_ROLE_DELETED",
1976 Self::TemplateCreated => "AUDIT_EVENT_TYPE_TEMPLATE_CREATED",
1977 Self::TemplateUpdated => "AUDIT_EVENT_TYPE_TEMPLATE_UPDATED",
1978 Self::ApiKeyCreated => "AUDIT_EVENT_TYPE_API_KEY_CREATED",
1979 Self::ApiKeyRevoked => "AUDIT_EVENT_TYPE_API_KEY_REVOKED",
1980 Self::InviteLinkCreated => "AUDIT_EVENT_TYPE_INVITE_LINK_CREATED",
1981 Self::InviteLinkRevoked => "AUDIT_EVENT_TYPE_INVITE_LINK_REVOKED",
1982 Self::GroupCreated => "AUDIT_EVENT_TYPE_GROUP_CREATED",
1983 Self::GroupUpdated => "AUDIT_EVENT_TYPE_GROUP_UPDATED",
1984 Self::GroupDeleted => "AUDIT_EVENT_TYPE_GROUP_DELETED",
1985 Self::GroupMembersAdded => "AUDIT_EVENT_TYPE_GROUP_MEMBERS_ADDED",
1986 Self::GroupMembersRemoved => "AUDIT_EVENT_TYPE_GROUP_MEMBERS_REMOVED",
1987 Self::TeamCreated => "AUDIT_EVENT_TYPE_TEAM_CREATED",
1988 Self::TeamUpdated => "AUDIT_EVENT_TYPE_TEAM_UPDATED",
1989 Self::TeamDeleted => "AUDIT_EVENT_TYPE_TEAM_DELETED",
1990 Self::TeamMembersAdded => "AUDIT_EVENT_TYPE_TEAM_MEMBERS_ADDED",
1991 Self::TeamMembersRemoved => "AUDIT_EVENT_TYPE_TEAM_MEMBERS_REMOVED",
1992 Self::ScimUserProvisioned => "AUDIT_EVENT_TYPE_SCIM_USER_PROVISIONED",
1993 Self::ScimUserDeprovisioned => "AUDIT_EVENT_TYPE_SCIM_USER_DEPROVISIONED",
1994 Self::ScimUserUpdated => "AUDIT_EVENT_TYPE_SCIM_USER_UPDATED",
1995 Self::TranslationCreated => "AUDIT_EVENT_TYPE_TRANSLATION_CREATED",
1996 Self::TranslationApproved => "AUDIT_EVENT_TYPE_TRANSLATION_APPROVED",
1997 Self::SandboxCreated => "AUDIT_EVENT_TYPE_SANDBOX_CREATED",
1998 Self::SandboxExpired => "AUDIT_EVENT_TYPE_SANDBOX_EXPIRED",
1999 Self::AiPredictionLogged => "AUDIT_EVENT_TYPE_AI_PREDICTION_LOGGED",
2000 Self::MlPipelineTriggered => "AUDIT_EVENT_TYPE_ML_PIPELINE_TRIGGERED",
2001 Self::ArchetypeClusteringTriggered => "AUDIT_EVENT_TYPE_ARCHETYPE_CLUSTERING_TRIGGERED",
2002 Self::OrgCreated => "AUDIT_EVENT_TYPE_ORG_CREATED",
2003 Self::OrgDeleted => "AUDIT_EVENT_TYPE_ORG_DELETED",
2004 Self::ReachabilityUpsert => "AUDIT_EVENT_TYPE_REACHABILITY_UPSERT",
2005 Self::ReachabilityRemove => "AUDIT_EVENT_TYPE_REACHABILITY_REMOVE",
2006 Self::KmsEncrypt => "AUDIT_EVENT_TYPE_KMS_ENCRYPT",
2007 Self::KmsDecrypt => "AUDIT_EVENT_TYPE_KMS_DECRYPT",
2008 }
2009 }
2010 /// Creates an enum from field names used in the ProtoBuf definition.
2011 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
2012 match value {
2013 "AUDIT_EVENT_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
2014 "AUDIT_EVENT_TYPE_CAMPAIGN_CREATED" => Some(Self::CampaignCreated),
2015 "AUDIT_EVENT_TYPE_MESSAGE_SENT" => Some(Self::MessageSent),
2016 "AUDIT_EVENT_TYPE_MESSAGE_OPENED" => Some(Self::MessageOpened),
2017 "AUDIT_EVENT_TYPE_ACK_REGISTERED" => Some(Self::AckRegistered),
2018 "AUDIT_EVENT_TYPE_ESCALATION_EXECUTED" => Some(Self::EscalationExecuted),
2019 "AUDIT_EVENT_TYPE_CAMPAIGN_STARTED" => Some(Self::CampaignStarted),
2020 "AUDIT_EVENT_TYPE_CAMPAIGN_CANCELLED" => Some(Self::CampaignCancelled),
2021 "AUDIT_EVENT_TYPE_CAMPAIGN_UPDATED" => Some(Self::CampaignUpdated),
2022 "AUDIT_EVENT_TYPE_USER_INVITED" => Some(Self::UserInvited),
2023 "AUDIT_EVENT_TYPE_USER_DEACTIVATED" => Some(Self::UserDeactivated),
2024 "AUDIT_EVENT_TYPE_USER_REACTIVATED" => Some(Self::UserReactivated),
2025 "AUDIT_EVENT_TYPE_ROLE_CHANGED" => Some(Self::RoleChanged),
2026 "AUDIT_EVENT_TYPE_INVITE_REVOKED" => Some(Self::InviteRevoked),
2027 "AUDIT_EVENT_TYPE_PROFILE_UPDATED" => Some(Self::ProfileUpdated),
2028 "AUDIT_EVENT_TYPE_SETTINGS_UPDATED" => Some(Self::SettingsUpdated),
2029 "AUDIT_EVENT_TYPE_PASSKEY_ENROLLED" => Some(Self::PasskeyEnrolled),
2030 "AUDIT_EVENT_TYPE_DATA_EXPORT_REQUESTED" => Some(Self::DataExportRequested),
2031 "AUDIT_EVENT_TYPE_DATA_DELETION_REQUESTED" => Some(Self::DataDeletionRequested),
2032 "AUDIT_EVENT_TYPE_DATA_RECTIFIED" => Some(Self::DataRectified),
2033 "AUDIT_EVENT_TYPE_PROCESSING_RESTRICTED" => Some(Self::ProcessingRestricted),
2034 "AUDIT_EVENT_TYPE_DELETION_CANCELLED" => Some(Self::DeletionCancelled),
2035 "AUDIT_EVENT_TYPE_DELETION_IMMEDIATE" => Some(Self::DeletionImmediate),
2036 "AUDIT_EVENT_TYPE_SSO_CONFIGURED" => Some(Self::SsoConfigured),
2037 "AUDIT_EVENT_TYPE_SSO_PROVIDER_CREATED" => Some(Self::SsoProviderCreated),
2038 "AUDIT_EVENT_TYPE_SSO_PROVIDER_DELETED" => Some(Self::SsoProviderDeleted),
2039 "AUDIT_EVENT_TYPE_ORG_UPDATED" => Some(Self::OrgUpdated),
2040 "AUDIT_EVENT_TYPE_ROLE_CREATED" => Some(Self::RoleCreated),
2041 "AUDIT_EVENT_TYPE_ROLE_UPDATED" => Some(Self::RoleUpdated),
2042 "AUDIT_EVENT_TYPE_ROLE_DELETED" => Some(Self::RoleDeleted),
2043 "AUDIT_EVENT_TYPE_TEMPLATE_CREATED" => Some(Self::TemplateCreated),
2044 "AUDIT_EVENT_TYPE_TEMPLATE_UPDATED" => Some(Self::TemplateUpdated),
2045 "AUDIT_EVENT_TYPE_API_KEY_CREATED" => Some(Self::ApiKeyCreated),
2046 "AUDIT_EVENT_TYPE_API_KEY_REVOKED" => Some(Self::ApiKeyRevoked),
2047 "AUDIT_EVENT_TYPE_INVITE_LINK_CREATED" => Some(Self::InviteLinkCreated),
2048 "AUDIT_EVENT_TYPE_INVITE_LINK_REVOKED" => Some(Self::InviteLinkRevoked),
2049 "AUDIT_EVENT_TYPE_GROUP_CREATED" => Some(Self::GroupCreated),
2050 "AUDIT_EVENT_TYPE_GROUP_UPDATED" => Some(Self::GroupUpdated),
2051 "AUDIT_EVENT_TYPE_GROUP_DELETED" => Some(Self::GroupDeleted),
2052 "AUDIT_EVENT_TYPE_GROUP_MEMBERS_ADDED" => Some(Self::GroupMembersAdded),
2053 "AUDIT_EVENT_TYPE_GROUP_MEMBERS_REMOVED" => Some(Self::GroupMembersRemoved),
2054 "AUDIT_EVENT_TYPE_TEAM_CREATED" => Some(Self::TeamCreated),
2055 "AUDIT_EVENT_TYPE_TEAM_UPDATED" => Some(Self::TeamUpdated),
2056 "AUDIT_EVENT_TYPE_TEAM_DELETED" => Some(Self::TeamDeleted),
2057 "AUDIT_EVENT_TYPE_TEAM_MEMBERS_ADDED" => Some(Self::TeamMembersAdded),
2058 "AUDIT_EVENT_TYPE_TEAM_MEMBERS_REMOVED" => Some(Self::TeamMembersRemoved),
2059 "AUDIT_EVENT_TYPE_SCIM_USER_PROVISIONED" => Some(Self::ScimUserProvisioned),
2060 "AUDIT_EVENT_TYPE_SCIM_USER_DEPROVISIONED" => Some(Self::ScimUserDeprovisioned),
2061 "AUDIT_EVENT_TYPE_SCIM_USER_UPDATED" => Some(Self::ScimUserUpdated),
2062 "AUDIT_EVENT_TYPE_TRANSLATION_CREATED" => Some(Self::TranslationCreated),
2063 "AUDIT_EVENT_TYPE_TRANSLATION_APPROVED" => Some(Self::TranslationApproved),
2064 "AUDIT_EVENT_TYPE_SANDBOX_CREATED" => Some(Self::SandboxCreated),
2065 "AUDIT_EVENT_TYPE_SANDBOX_EXPIRED" => Some(Self::SandboxExpired),
2066 "AUDIT_EVENT_TYPE_AI_PREDICTION_LOGGED" => Some(Self::AiPredictionLogged),
2067 "AUDIT_EVENT_TYPE_ML_PIPELINE_TRIGGERED" => Some(Self::MlPipelineTriggered),
2068 "AUDIT_EVENT_TYPE_ARCHETYPE_CLUSTERING_TRIGGERED" => Some(Self::ArchetypeClusteringTriggered),
2069 "AUDIT_EVENT_TYPE_ORG_CREATED" => Some(Self::OrgCreated),
2070 "AUDIT_EVENT_TYPE_ORG_DELETED" => Some(Self::OrgDeleted),
2071 "AUDIT_EVENT_TYPE_REACHABILITY_UPSERT" => Some(Self::ReachabilityUpsert),
2072 "AUDIT_EVENT_TYPE_REACHABILITY_REMOVE" => Some(Self::ReachabilityRemove),
2073 "AUDIT_EVENT_TYPE_KMS_ENCRYPT" => Some(Self::KmsEncrypt),
2074 "AUDIT_EVENT_TYPE_KMS_DECRYPT" => Some(Self::KmsDecrypt),
2075 _ => None,
2076 }
2077 }
2078}
2079/// Classification of an audit event by origin and volume profile, separating
2080/// management actions (human-initiated configuration changes) from high-volume
2081/// system events emitted automatically during processing.
2082#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2083#[repr(i32)]
2084pub enum AuditEventClass {
2085 /// Default value; should not be used explicitly.
2086 Unspecified = 0,
2087 /// An action initiated by a principal against the organization's
2088 /// configuration or operation (e.g. creating a campaign, changing a role).
2089 Management = 1,
2090 /// A high-volume data-plane event emitted by the system during processing
2091 /// (e.g. per-payload encryption or decryption).
2092 System = 2,
2093}
2094impl AuditEventClass {
2095 /// String value of the enum field names used in the ProtoBuf definition.
2096 ///
2097 /// The values are not transformed in any way and thus are considered stable
2098 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
2099 pub fn as_str_name(&self) -> &'static str {
2100 match self {
2101 Self::Unspecified => "AUDIT_EVENT_CLASS_UNSPECIFIED",
2102 Self::Management => "AUDIT_EVENT_CLASS_MANAGEMENT",
2103 Self::System => "AUDIT_EVENT_CLASS_SYSTEM",
2104 }
2105 }
2106 /// Creates an enum from field names used in the ProtoBuf definition.
2107 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
2108 match value {
2109 "AUDIT_EVENT_CLASS_UNSPECIFIED" => Some(Self::Unspecified),
2110 "AUDIT_EVENT_CLASS_MANAGEMENT" => Some(Self::Management),
2111 "AUDIT_EVENT_CLASS_SYSTEM" => Some(Self::System),
2112 _ => None,
2113 }
2114 }
2115}
2116/// Format for audit trail export.
2117#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2118#[repr(i32)]
2119pub enum AuditExportFormat {
2120 /// Default value; should not be used explicitly.
2121 Unspecified = 0,
2122 /// Comma-separated values.
2123 Csv = 1,
2124 /// JSON lines format.
2125 Json = 2,
2126 /// Apache Parquet columnar format.
2127 Parquet = 3,
2128}
2129impl AuditExportFormat {
2130 /// String value of the enum field names used in the ProtoBuf definition.
2131 ///
2132 /// The values are not transformed in any way and thus are considered stable
2133 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
2134 pub fn as_str_name(&self) -> &'static str {
2135 match self {
2136 Self::Unspecified => "AUDIT_EXPORT_FORMAT_UNSPECIFIED",
2137 Self::Csv => "AUDIT_EXPORT_FORMAT_CSV",
2138 Self::Json => "AUDIT_EXPORT_FORMAT_JSON",
2139 Self::Parquet => "AUDIT_EXPORT_FORMAT_PARQUET",
2140 }
2141 }
2142 /// Creates an enum from field names used in the ProtoBuf definition.
2143 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
2144 match value {
2145 "AUDIT_EXPORT_FORMAT_UNSPECIFIED" => Some(Self::Unspecified),
2146 "AUDIT_EXPORT_FORMAT_CSV" => Some(Self::Csv),
2147 "AUDIT_EXPORT_FORMAT_JSON" => Some(Self::Json),
2148 "AUDIT_EXPORT_FORMAT_PARQUET" => Some(Self::Parquet),
2149 _ => None,
2150 }
2151 }
2152}
2153// ─── Messages ─────────────────────────────────────────────────────────────────
2154
2155/// Request to resolve the effective permission set for one principal.
2156#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2157pub struct ResolvePrincipalPermissionsRequest {
2158 /// UUID of the subject whose permissions are being resolved (user or
2159 /// principal identifier).
2160 #[prost(string, tag="1")]
2161 pub subject: ::prost::alloc::string::String,
2162 /// Organization the resolution is scoped to.
2163 #[prost(string, tag="2")]
2164 pub org_id: ::prost::alloc::string::String,
2165 /// Kind of principal identified by `subject`.
2166 #[prost(enumeration="PrincipalType", tag="3")]
2167 pub principal_type: i32,
2168}
2169/// Effective permissions resolved for the requested principal.
2170#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2171pub struct ResolvePrincipalPermissionsResponse {
2172 /// Flattened, deduplicated set of permissions granted to the principal in
2173 /// the requested organization. Empty when the principal has no grants.
2174 #[prost(enumeration="Permission", repeated, tag="1")]
2175 pub permissions: ::prost::alloc::vec::Vec<i32>,
2176}
2177/// Request to check the current suspension state of one organization.
2178#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2179pub struct CheckOrgSuspendedRequest {
2180 /// Organization whose suspension state is being checked.
2181 #[prost(string, tag="1")]
2182 pub org_id: ::prost::alloc::string::String,
2183}
2184/// Current suspension state of the requested organization.
2185#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
2186pub struct CheckOrgSuspendedResponse {
2187 /// True when the organization is currently suspended.
2188 #[prost(bool, tag="1")]
2189 pub suspended: bool,
2190}
2191// ─── Enums ──────────────────────────────────────────────────────────────────
2192
2193/// Kind of principal whose permissions are being resolved.
2194#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2195#[repr(i32)]
2196pub enum PrincipalType {
2197 Unspecified = 0,
2198 /// An end user identified by their user UUID, scoped to one organization.
2199 User = 1,
2200 /// An organization acting as its own principal (e.g. a service identity
2201 /// operating on behalf of the whole org rather than a member).
2202 Org = 2,
2203 /// A platform staff principal whose permissions derive from a role within
2204 /// the ORG_TYPE_STAFF organization.
2205 Staff = 3,
2206}
2207impl PrincipalType {
2208 /// String value of the enum field names used in the ProtoBuf definition.
2209 ///
2210 /// The values are not transformed in any way and thus are considered stable
2211 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
2212 pub fn as_str_name(&self) -> &'static str {
2213 match self {
2214 Self::Unspecified => "PRINCIPAL_TYPE_UNSPECIFIED",
2215 Self::User => "PRINCIPAL_TYPE_USER",
2216 Self::Org => "PRINCIPAL_TYPE_ORG",
2217 Self::Staff => "PRINCIPAL_TYPE_STAFF",
2218 }
2219 }
2220 /// Creates an enum from field names used in the ProtoBuf definition.
2221 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
2222 match value {
2223 "PRINCIPAL_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
2224 "PRINCIPAL_TYPE_USER" => Some(Self::User),
2225 "PRINCIPAL_TYPE_ORG" => Some(Self::Org),
2226 "PRINCIPAL_TYPE_STAFF" => Some(Self::Staff),
2227 _ => None,
2228 }
2229 }
2230}
2231// ─── Messages ───────────────────────────────────────────────────────────────
2232
2233/// A campaign that delivers structured messages to a set of recipients
2234/// and tracks their engagement through a workflow.
2235#[derive(Clone, PartialEq, ::prost::Message)]
2236pub struct Campaign {
2237 /// Unique identifier for the campaign.
2238 /// Constraints: UUID format (36 characters).
2239 #[prost(string, tag="1")]
2240 pub id: ::prost::alloc::string::String,
2241 /// Human-readable campaign name.
2242 /// Constraints: Max length 200 characters.
2243 #[prost(string, tag="2")]
2244 pub name: ::prost::alloc::string::String,
2245 /// ID of the template used to render messages.
2246 /// Constraints: UUID format (36 characters).
2247 #[prost(string, tag="3")]
2248 pub template_id: ::prost::alloc::string::String,
2249 /// Pinned version of the template used for this campaign.
2250 #[prost(int32, tag="4")]
2251 pub template_version: i32,
2252 /// Object storage reference to the audience snapshot taken at campaign creation.
2253 #[prost(string, tag="5")]
2254 pub audience_snapshot_ref: ::prost::alloc::string::String,
2255 /// Current lifecycle status of the campaign.
2256 #[prost(enumeration="CampaignStatus", tag="6")]
2257 pub status: i32,
2258 /// Workflow DAG that drives the campaign's automation logic.
2259 #[prost(message, optional, tag="7")]
2260 pub workflow: ::core::option::Option<WorkflowDefinition>,
2261 /// Total number of recipients in the audience snapshot.
2262 #[prost(int32, tag="8")]
2263 pub total_recipients: i32,
2264 /// Number of recipients who completed the required action.
2265 #[prost(int32, tag="9")]
2266 pub action_completed_count: i32,
2267 /// Number of recipients who did not act before the deadline.
2268 #[prost(int32, tag="10")]
2269 pub missed_count: i32,
2270 /// Timestamp when the campaign was created.
2271 #[prost(message, optional, tag="11")]
2272 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
2273 /// Timestamp when the campaign was started (workflow execution began).
2274 #[prost(message, optional, tag="12")]
2275 pub started_at: ::core::option::Option<::prost_types::Timestamp>,
2276 /// Timestamp when the campaign finished (completed, failed, or cancelled).
2277 #[prost(message, optional, tag="13")]
2278 pub completed_at: ::core::option::Option<::prost_types::Timestamp>,
2279 /// Display name of the sender shown to recipients (e.g. "HR Team").
2280 /// Constraints: Max length 200 characters.
2281 #[prost(string, tag="14")]
2282 pub sender_name: ::prost::alloc::string::String,
2283 /// Optional user-facing title override. If set, takes precedence over the template title.
2284 /// Constraints: Max length 200 characters.
2285 #[prost(string, tag="15")]
2286 pub title: ::prost::alloc::string::String,
2287 /// Whether this campaign's notifications break through Do Not Disturb / Focus mode.
2288 #[prost(bool, tag="16")]
2289 pub critical: bool,
2290 /// Optional locale override for all recipients in this campaign.
2291 /// When set, all recipients receive the campaign in this locale regardless of
2292 /// their preferred_locale. Empty means per-recipient locale resolution.
2293 /// Valid values: en, es, pt-BR, zh, ja.
2294 #[prost(string, tag="17")]
2295 pub default_locale: ::prost::alloc::string::String,
2296 /// Whether the campaign deadline waits for users without registered devices.
2297 /// When true, NO_DEVICE users remain in pending_count and can acknowledge
2298 /// via inbox after installing the app. Default false preserves current behavior.
2299 #[prost(bool, tag="18")]
2300 pub wait_for_enrollment: bool,
2301 /// Optional. Set when the campaign was created from a Compass archetype CTA.
2302 /// Drives post-campaign archetype-response analytics.
2303 #[prost(message, optional, tag="19")]
2304 pub originating_archetype: ::core::option::Option<CampaignOriginatingArchetype>,
2305 /// True when this campaign contains synthetic (artificially injected) data —
2306 /// created or populated for demos, sandbox testing, or issue reproduction.
2307 #[prost(bool, tag="20")]
2308 pub synthetic: bool,
2309 /// Number of recipients frozen in the audience snapshot at creation time.
2310 /// Unlike total_recipients (which counts deliveries and is 0 until the
2311 /// campaign starts), this is known as soon as the campaign exists.
2312 /// 0 when the campaign predates snapshot-size tracking.
2313 #[prost(int32, tag="21")]
2314 pub audience_snapshot_size: i32,
2315 /// Number of members currently eligible for this campaign's audience,
2316 /// computed at read time. Compare with audience_snapshot_size to see how far
2317 /// the frozen audience has drifted from the present membership.
2318 #[prost(int32, tag="22")]
2319 pub current_audience_size: i32,
2320 /// True when the frozen audience no longer covers the current eligible
2321 /// membership (current_audience_size > audience_snapshot_size). Clients
2322 /// should surface this before the campaign is started: recipients added
2323 /// after creation are NOT reached unless the campaign is recreated.
2324 #[prost(bool, tag="23")]
2325 pub audience_snapshot_stale: bool,
2326 /// Live execution position of the campaign's workflow. Unset until the
2327 /// campaign starts and after it reaches a terminal state. Distinct from
2328 /// per-recipient delivery state: this reports which workflow step the
2329 /// engine is executing (or waiting on), independent of whether any
2330 /// recipient has acted.
2331 #[prost(message, optional, tag="24")]
2332 pub workflow_progress: ::core::option::Option<CampaignWorkflowProgress>,
2333 /// Objectives this campaign serves, as declared at creation or linked
2334 /// afterwards. Empty is allowed and carries no penalty: a campaign
2335 /// with no declared objective behaves exactly like one that predates
2336 /// objectives entirely.
2337 #[prost(string, repeated, tag="25")]
2338 pub objective_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
2339}
2340/// Live execution position of a running campaign's workflow, recorded by
2341/// the campaign worker as steps transition. Lets clients render true
2342/// engine progress (e.g. "waiting on a deadline until T") instead of
2343/// inferring it from recipient delivery activity, which never observes
2344/// timer-only steps.
2345#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2346pub struct CampaignWorkflowProgress {
2347 /// Workflow-definition step id (WorkflowStep.id) currently executing or
2348 /// being waited on.
2349 #[prost(string, tag="1")]
2350 pub current_step_id: ::prost::alloc::string::String,
2351 /// When the workflow entered the current step.
2352 #[prost(message, optional, tag="2")]
2353 pub step_entered_at: ::core::option::Option<::prost_types::Timestamp>,
2354 /// For timer-backed steps (e.g. deadline checks): when the pending timer
2355 /// fires. Unset for steps that complete without waiting.
2356 #[prost(message, optional, tag="3")]
2357 pub next_wake_at: ::core::option::Option<::prost_types::Timestamp>,
2358}
2359/// Identifies the archetype that motivated the creation of a campaign.
2360/// The audience is NOT filtered by archetype membership — this is metadata
2361/// about the campaign's authoring intent only. See OpenSpec change
2362/// archetype-targeted-campaign-cta.
2363#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2364pub struct CampaignOriginatingArchetype {
2365 /// UUID of the group whose archetype set the label belongs to.
2366 #[prost(string, tag="1")]
2367 pub group_id: ::prost::alloc::string::String,
2368 /// Stable archetype label (e.g., "Swift Acknowledger"). Labels are stable
2369 /// across clustering retrains; archetype IDs are not.
2370 #[prost(string, tag="2")]
2371 pub archetype_label: ::prost::alloc::string::String,
2372}
2373/// A single audience member with optional per-user template variables.
2374#[derive(Clone, PartialEq, ::prost::Message)]
2375pub struct AudienceMember {
2376 /// User ID (UUID).
2377 #[prost(string, tag="1")]
2378 pub user_id: ::prost::alloc::string::String,
2379 /// Template variable values for this user (e.g. {"name": "Alice"}).
2380 #[prost(map="string, string", tag="2")]
2381 pub variables: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
2382}
2383/// Request to create a new campaign.
2384#[derive(Clone, PartialEq, ::prost::Message)]
2385pub struct CreateCampaignRequest {
2386 /// Human-readable campaign name (admin-facing label).
2387 /// Constraints: Max length 200 characters.
2388 #[prost(string, tag="1")]
2389 pub name: ::prost::alloc::string::String,
2390 /// ID of the template to use for rendering messages.
2391 /// Constraints: UUID format (36 characters).
2392 #[prost(string, tag="2")]
2393 pub template_id: ::prost::alloc::string::String,
2394 /// Version of the template to pin for this campaign.
2395 #[prost(int32, tag="3")]
2396 pub template_version: i32,
2397 /// List of user IDs that form the campaign audience.
2398 /// Constraints: Max 100000 items.
2399 #[prost(string, repeated, tag="4")]
2400 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
2401 /// Workflow DAG defining the campaign's automation steps.
2402 /// Required: CreateCampaign rejects a request with no workflow
2403 /// (INVALID_ARGUMENT) and does not substitute a default. The definition
2404 /// MUST validate as an acyclic graph of well-formed steps.
2405 #[prost(message, optional, tag="5")]
2406 pub workflow: ::core::option::Option<WorkflowDefinition>,
2407 /// Display name of the sender shown to recipients (e.g. "HR Team").
2408 /// Constraints: Max length 200 characters.
2409 #[prost(string, tag="6")]
2410 pub sender_name: ::prost::alloc::string::String,
2411 /// Optional user-facing title override. If empty, the template title is used.
2412 /// Constraints: Max length 200 characters.
2413 #[prost(string, tag="7")]
2414 pub title: ::prost::alloc::string::String,
2415 /// Rich audience with per-user template variables.
2416 /// When set, takes precedence over user_ids.
2417 /// Constraints: Max 100000 items.
2418 #[prost(message, repeated, tag="8")]
2419 pub audience: ::prost::alloc::vec::Vec<AudienceMember>,
2420 /// Whether to include users with processing_restricted=true in the audience.
2421 /// Default false: restricted users are excluded. Set true only with Art. 18(2) legal basis.
2422 #[prost(bool, tag="9")]
2423 pub include_restricted: bool,
2424 /// Whether this campaign's notifications break through Do Not Disturb / Focus mode.
2425 #[prost(bool, tag="10")]
2426 pub critical: bool,
2427 /// Optional locale override for all recipients.
2428 #[prost(string, tag="11")]
2429 pub default_locale: ::prost::alloc::string::String,
2430 /// Whether the campaign deadline should wait for users without registered devices.
2431 /// When true, NO_DEVICE users are not decremented from pending_count,
2432 /// allowing them to acknowledge via inbox after installing the app.
2433 #[prost(bool, tag="12")]
2434 pub wait_for_enrollment: bool,
2435 /// Optional. Set when the campaign is created from a Compass archetype CTA.
2436 /// The server validates the caller has access to group_id and that
2437 /// archetype_label exists in the group's current archetype set; cross-org
2438 /// group_id returns PERMISSION_DENIED, unknown label returns NOT_FOUND.
2439 #[prost(message, optional, tag="13")]
2440 pub originating_archetype: ::core::option::Option<CampaignOriginatingArchetype>,
2441 /// Objectives this campaign serves. Declaring the objective at
2442 /// creation is the point at which a response rate stops being the
2443 /// result and becomes evidence about something the organization was
2444 /// trying to achieve. Empty is allowed and changes nothing about how
2445 /// the campaign runs. Unknown or cross-org IDs return NOT_FOUND.
2446 #[prost(string, repeated, tag="14")]
2447 pub objective_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
2448}
2449/// Response after creating a campaign.
2450#[derive(Clone, PartialEq, ::prost::Message)]
2451pub struct CreateCampaignResponse {
2452 /// The newly created campaign.
2453 #[prost(message, optional, tag="1")]
2454 pub campaign: ::core::option::Option<Campaign>,
2455}
2456/// Request to start a campaign's workflow execution.
2457#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2458pub struct StartCampaignRequest {
2459 /// ID of the campaign to start.
2460 /// Constraints: UUID format (36 characters).
2461 #[prost(string, tag="1")]
2462 pub campaign_id: ::prost::alloc::string::String,
2463}
2464/// Response after starting a campaign.
2465#[derive(Clone, PartialEq, ::prost::Message)]
2466pub struct StartCampaignResponse {
2467 /// The campaign with updated status.
2468 #[prost(message, optional, tag="1")]
2469 pub campaign: ::core::option::Option<Campaign>,
2470}
2471/// Request to retrieve a single campaign by ID.
2472#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2473pub struct GetCampaignRequest {
2474 /// ID of the campaign to retrieve.
2475 /// Constraints: UUID format (36 characters).
2476 #[prost(string, tag="1")]
2477 pub campaign_id: ::prost::alloc::string::String,
2478}
2479/// Response containing the requested campaign.
2480#[derive(Clone, PartialEq, ::prost::Message)]
2481pub struct GetCampaignResponse {
2482 /// The requested campaign.
2483 #[prost(message, optional, tag="1")]
2484 pub campaign: ::core::option::Option<Campaign>,
2485}
2486/// Request to list campaigns with pagination.
2487#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2488pub struct ListCampaignsRequest {
2489 /// Pagination parameters.
2490 #[prost(message, optional, tag="1")]
2491 pub pagination: ::core::option::Option<Pagination>,
2492}
2493/// Response containing a page of campaigns.
2494#[derive(Clone, PartialEq, ::prost::Message)]
2495pub struct ListCampaignsResponse {
2496 /// List of campaigns in this page.
2497 #[prost(message, repeated, tag="1")]
2498 pub campaigns: ::prost::alloc::vec::Vec<Campaign>,
2499 /// Pagination metadata for fetching subsequent pages.
2500 #[prost(message, optional, tag="2")]
2501 pub pagination_meta: ::core::option::Option<PaginationMeta>,
2502}
2503/// Request to cancel a running campaign.
2504#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2505pub struct CancelCampaignRequest {
2506 /// ID of the campaign to cancel.
2507 /// Constraints: UUID format (36 characters).
2508 #[prost(string, tag="1")]
2509 pub campaign_id: ::prost::alloc::string::String,
2510}
2511/// Response after cancelling a campaign.
2512#[derive(Clone, PartialEq, ::prost::Message)]
2513pub struct CancelCampaignResponse {
2514 /// The campaign with updated status (CANCELLED).
2515 #[prost(message, optional, tag="1")]
2516 pub campaign: ::core::option::Option<Campaign>,
2517}
2518/// Request to update a draft campaign (status must be CREATED).
2519/// Only non-empty/non-zero fields are updated; omitted fields remain unchanged.
2520#[derive(Clone, PartialEq, ::prost::Message)]
2521pub struct UpdateCampaignRequest {
2522 /// ID of the campaign to update.
2523 /// Constraints: UUID format (36 characters).
2524 #[prost(string, tag="1")]
2525 pub campaign_id: ::prost::alloc::string::String,
2526 /// Updated campaign name. Empty string means no change.
2527 /// Constraints: Max length 200 characters.
2528 #[prost(string, tag="2")]
2529 pub name: ::prost::alloc::string::String,
2530 /// Updated sender display name. Empty string means no change.
2531 /// Constraints: Max length 200 characters.
2532 #[prost(string, tag="3")]
2533 pub sender_name: ::prost::alloc::string::String,
2534 /// Updated title override. Empty string means no change.
2535 /// Constraints: Max length 200 characters.
2536 #[prost(string, tag="4")]
2537 pub title: ::prost::alloc::string::String,
2538 /// Updated template ID. Empty string means no change.
2539 /// Constraints: UUID format (36 characters).
2540 #[prost(string, tag="5")]
2541 pub template_id: ::prost::alloc::string::String,
2542 /// Updated template version. Zero means no change.
2543 #[prost(int32, tag="6")]
2544 pub template_version: i32,
2545 /// Updated workflow DAG. Null/omitted means no change.
2546 #[prost(message, optional, tag="7")]
2547 pub workflow: ::core::option::Option<WorkflowDefinition>,
2548 /// Replaces the campaign's frozen audience snapshot. Omitted means no
2549 /// change; PRESENT means replace — including with an empty member list
2550 /// (a campaign with no recipients is a valid state). The wrapper message
2551 /// exists exactly for that presence distinction, which a bare repeated
2552 /// field cannot express. Only valid while the campaign is in CREATED
2553 /// status; the server rejects the replacement once the campaign has
2554 /// started, since deliveries were already created from the old snapshot.
2555 #[prost(message, optional, tag="8")]
2556 pub audience_replacement: ::core::option::Option<AudienceReplacement>,
2557}
2558/// A full replacement for a campaign's frozen audience. Presence of this
2559/// message (not its member count) signals the replace intent.
2560#[derive(Clone, PartialEq, ::prost::Message)]
2561pub struct AudienceReplacement {
2562 /// The new complete audience. Replaces the previous snapshot wholesale.
2563 #[prost(message, repeated, tag="1")]
2564 pub members: ::prost::alloc::vec::Vec<AudienceMember>,
2565}
2566/// Response after updating a campaign.
2567#[derive(Clone, PartialEq, ::prost::Message)]
2568pub struct UpdateCampaignResponse {
2569 /// The campaign with updated fields.
2570 #[prost(message, optional, tag="1")]
2571 pub campaign: ::core::option::Option<Campaign>,
2572}
2573/// Request to read a campaign's frozen audience snapshot.
2574#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2575pub struct GetCampaignAudienceRequest {
2576 /// ID of the campaign whose audience to read.
2577 /// Constraints: UUID format (36 characters).
2578 #[prost(string, tag="1")]
2579 pub campaign_id: ::prost::alloc::string::String,
2580}
2581/// One member of a campaign's frozen audience, enriched with the identity
2582/// fields a client needs to render the member without further lookups.
2583#[derive(Clone, PartialEq, ::prost::Message)]
2584pub struct CampaignAudienceEntry {
2585 /// The frozen audience row exactly as it will be delivered to: user id
2586 /// plus per-user template variables.
2587 #[prost(message, optional, tag="1")]
2588 pub member: ::core::option::Option<AudienceMember>,
2589 /// The member's email at read time. Empty when the user no longer
2590 /// resolves (deactivated or erased since the audience was frozen).
2591 #[prost(string, tag="2")]
2592 pub email: ::prost::alloc::string::String,
2593 /// The member's display name at read time. Empty when unresolvable.
2594 #[prost(string, tag="3")]
2595 pub display_name: ::prost::alloc::string::String,
2596 /// False when the user is no longer an active or invited member of the
2597 /// organization — a frozen recipient that would not be reachable today.
2598 #[prost(bool, tag="4")]
2599 pub active: bool,
2600}
2601/// A campaign's frozen audience. Empty when the campaign has no audience
2602/// snapshot (legacy campaigns predating snapshot tracking) or the snapshot
2603/// is empty.
2604#[derive(Clone, PartialEq, ::prost::Message)]
2605pub struct GetCampaignAudienceResponse {
2606 /// The frozen audience, enriched per entry.
2607 #[prost(message, repeated, tag="1")]
2608 pub entries: ::prost::alloc::vec::Vec<CampaignAudienceEntry>,
2609}
2610/// A single delivery record tracking message delivery to one recipient.
2611/// Out-of-band context attached to a delivery beyond its canonical
2612/// recipient + status + content payload. Optional; fields are populated
2613/// per delivery kind. Currently only REMINDER_FYI children carry values,
2614/// to snapshot context from the parent delivery so clients can render
2615/// without fetching additional resources.
2616#[derive(Clone, PartialEq, ::prost::Message)]
2617pub struct DeliveryMetadata {
2618 /// REMINDER_FYI: the rendered Message payload from the parent delivery,
2619 /// used to render the blockquoted "Original message" panel on the
2620 /// notify-target's inbox card.
2621 #[prost(message, optional, tag="1")]
2622 pub original_message: ::core::option::Option<Message>,
2623 /// REMINDER_FYI: display name of the original recipient (the employee
2624 /// who hasn't responded). Used to interpolate the FYI title and banner.
2625 #[prost(string, tag="2")]
2626 pub original_recipient_name: ::prost::alloc::string::String,
2627 /// REMINDER_FYI: campaign title, denormalized so the notify-target's
2628 /// client can render without a separate campaign lookup.
2629 #[prost(string, tag="3")]
2630 pub campaign_title: ::prost::alloc::string::String,
2631 /// REMINDER_FYI: when the parent reminder step fired, used to render
2632 /// the "fired X ago" footer on the FYI card.
2633 #[prost(message, optional, tag="4")]
2634 pub reminder_fired_at: ::core::option::Option<::prost_types::Timestamp>,
2635}
2636#[derive(Clone, PartialEq, ::prost::Message)]
2637pub struct Delivery {
2638 /// Unique identifier for this delivery.
2639 /// Constraints: UUID format (36 characters).
2640 #[prost(string, tag="1")]
2641 pub id: ::prost::alloc::string::String,
2642 /// ID of the recipient user.
2643 /// Constraints: UUID format (36 characters).
2644 #[prost(string, tag="2")]
2645 pub user_id: ::prost::alloc::string::String,
2646 /// ID of the campaign this delivery belongs to.
2647 /// Constraints: UUID format (36 characters).
2648 #[prost(string, tag="3")]
2649 pub campaign_id: ::prost::alloc::string::String,
2650 /// Current delivery status.
2651 #[prost(enumeration="DeliveryStatus", tag="4")]
2652 pub status: i32,
2653 /// Timestamp when the message was delivered to the device.
2654 #[prost(message, optional, tag="5")]
2655 pub delivered_at: ::core::option::Option<::prost_types::Timestamp>,
2656 /// Timestamp when the recipient read the message.
2657 #[prost(message, optional, tag="6")]
2658 pub read_at: ::core::option::Option<::prost_types::Timestamp>,
2659 /// Timestamp when the recipient performed the required action.
2660 #[prost(message, optional, tag="7")]
2661 pub acted_at: ::core::option::Option<::prost_types::Timestamp>,
2662 /// Email address of the recipient, populated from the users table on read.
2663 #[prost(string, tag="8")]
2664 pub recipient_email: ::prost::alloc::string::String,
2665 /// Discriminator distinguishing primary recipient deliveries from
2666 /// deliveries generated by downstream workflow steps.
2667 #[prost(enumeration="delivery::Kind", tag="12")]
2668 pub kind: i32,
2669 /// For non-primary deliveries, the UUID of the originating delivery this
2670 /// row was derived from. Empty for primary deliveries.
2671 /// Constraints: UUID format (36 characters) when set.
2672 #[prost(string, tag="13")]
2673 pub parent_delivery_id: ::prost::alloc::string::String,
2674 /// The locale this delivery's body was actually rendered in after fallback
2675 /// resolution (recipient preference, campaign override, template default).
2676 /// Valid values: en, es, pt-BR, zh, ja.
2677 #[prost(string, tag="14")]
2678 pub rendered_locale: ::prost::alloc::string::String,
2679 /// Optional out-of-band context. See `DeliveryMetadata` for which
2680 /// delivery kinds populate which fields. Empty for legacy / PRIMARY
2681 /// deliveries.
2682 #[prost(message, optional, tag="15")]
2683 pub metadata: ::core::option::Option<DeliveryMetadata>,
2684 /// True when this delivery's outcome is synthetic (artificially injected)
2685 /// data rather than the result of a real delivery and user response.
2686 #[prost(bool, tag="9")]
2687 pub synthetic: bool,
2688}
2689/// Nested message and enum types in `Delivery`.
2690pub mod delivery {
2691 /// Discriminator describing what produced this delivery row.
2692 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2693 #[repr(i32)]
2694 pub enum Kind {
2695 /// Default value; not a valid kind.
2696 Unspecified = 0,
2697 /// Delivery generated for an audience recipient at campaign start.
2698 Primary = 1,
2699 /// Delivery generated by an escalation step targeting a non-audience user.
2700 Escalation = 2,
2701 /// Passive heads-up delivery generated when a reminder step fans out to
2702 /// its `notify_targets`. Carries no action button; auto-dismisses when
2703 /// the parent delivery is acknowledged. See
2704 /// `SendReminderConfig.notify_targets`.
2705 ReminderFyi = 3,
2706 }
2707 impl Kind {
2708 /// String value of the enum field names used in the ProtoBuf definition.
2709 ///
2710 /// The values are not transformed in any way and thus are considered stable
2711 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
2712 pub fn as_str_name(&self) -> &'static str {
2713 match self {
2714 Self::Unspecified => "KIND_UNSPECIFIED",
2715 Self::Primary => "KIND_PRIMARY",
2716 Self::Escalation => "KIND_ESCALATION",
2717 Self::ReminderFyi => "KIND_REMINDER_FYI",
2718 }
2719 }
2720 /// Creates an enum from field names used in the ProtoBuf definition.
2721 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
2722 match value {
2723 "KIND_UNSPECIFIED" => Some(Self::Unspecified),
2724 "KIND_PRIMARY" => Some(Self::Primary),
2725 "KIND_ESCALATION" => Some(Self::Escalation),
2726 "KIND_REMINDER_FYI" => Some(Self::ReminderFyi),
2727 _ => None,
2728 }
2729 }
2730 }
2731}
2732/// Request to list deliveries for a campaign with optional status filtering.
2733#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2734pub struct ListDeliveriesRequest {
2735 /// ID of the campaign to list deliveries for.
2736 /// Constraints: UUID format (36 characters).
2737 #[prost(string, tag="1")]
2738 pub campaign_id: ::prost::alloc::string::String,
2739 /// Optional filter by delivery status. UNSPECIFIED returns all.
2740 #[prost(enumeration="DeliveryStatus", tag="2")]
2741 pub status_filter: i32,
2742 /// Pagination parameters.
2743 #[prost(message, optional, tag="3")]
2744 pub pagination: ::core::option::Option<Pagination>,
2745}
2746/// Response containing a page of delivery records.
2747#[derive(Clone, PartialEq, ::prost::Message)]
2748pub struct ListDeliveriesResponse {
2749 /// List of deliveries in this page.
2750 #[prost(message, repeated, tag="1")]
2751 pub deliveries: ::prost::alloc::vec::Vec<Delivery>,
2752 /// Pagination metadata for fetching subsequent pages.
2753 #[prost(message, optional, tag="2")]
2754 pub pagination_meta: ::core::option::Option<PaginationMeta>,
2755}
2756/// Request to compute the archetype-tendency-shift surface for a campaign:
2757/// how each archetype's share of the originating group has moved between
2758/// the snapshot closest to campaign-creation time and the most recent
2759/// snapshot. Only valid for campaigns whose originating_archetype is set.
2760#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2761pub struct GetCampaignArchetypeBreakdownRequest {
2762 /// ID of the campaign to break down.
2763 /// Constraints: UUID format (36 characters).
2764 #[prost(string, tag="1")]
2765 pub campaign_id: ::prost::alloc::string::String,
2766}
2767/// Movement in one archetype's share of the originating group between the
2768/// "before" and "after" archetype-clustering snapshots. Cohort-level only;
2769/// no joining to user identity. The `is_origin` row is the archetype the
2770/// campaign was authored for.
2771#[derive(Clone, PartialEq, ::prost::Message)]
2772pub struct ArchetypeShareShift {
2773 /// Stable archetype label, e.g. "Swift Acknowledger".
2774 #[prost(string, tag="1")]
2775 pub label: ::prost::alloc::string::String,
2776 /// Archetype's share of the group at the snapshot closest to (but not
2777 /// after) the campaign's created_at. Range 0.0 – 1.0.
2778 #[prost(double, tag="2")]
2779 pub share_before: f64,
2780 /// Archetype's share of the group at the most recent snapshot. Range
2781 /// 0.0 – 1.0. Equals share_before when no clustering has run since.
2782 #[prost(double, tag="3")]
2783 pub share_after: f64,
2784 /// True when this row's label matches the campaign's
2785 /// originating_archetype.archetype_label.
2786 #[prost(bool, tag="4")]
2787 pub is_origin: bool,
2788 /// Count of email DELIVERED events recorded for this archetype's members
2789 /// across the campaign window. Denominator for both open-rate fields.
2790 #[prost(uint64, tag="5")]
2791 pub email_delivered_count: u64,
2792 /// Open rate excluding events flagged as Apple-MPP prefetches
2793 /// (prefetch_suspected=true). Range 0.0 – 1.0.
2794 #[prost(double, tag="6")]
2795 pub email_open_rate_real: f64,
2796 /// Open rate including all OPENED events, prefetches included.
2797 /// Range 0.0 – 1.0.
2798 #[prost(double, tag="7")]
2799 pub email_open_rate_raw: f64,
2800}
2801/// Response containing per-archetype share shifts. The admin renders
2802/// these as a comparison table — origin row marked, others as peers, so
2803/// the admin can tell campaign-coincident drift apart from background
2804/// drift across the rest of the group.
2805#[derive(Clone, PartialEq, ::prost::Message)]
2806pub struct GetCampaignArchetypeBreakdownResponse {
2807 /// One entry per archetype in the originating group. Empty when
2808 /// insufficient_history is true.
2809 #[prost(message, repeated, tag="1")]
2810 pub shifts: ::prost::alloc::vec::Vec<ArchetypeShareShift>,
2811 /// When the "before" sample was taken (closest snapshot at or before
2812 /// campaign creation).
2813 #[prost(message, optional, tag="2")]
2814 pub before_snapshot_at: ::core::option::Option<::prost_types::Timestamp>,
2815 /// When the "after" sample was taken (most recent snapshot).
2816 #[prost(message, optional, tag="3")]
2817 pub after_snapshot_at: ::core::option::Option<::prost_types::Timestamp>,
2818 /// True when fewer than two clustering snapshots exist for the group,
2819 /// so no shift can be computed yet. Admin renders an "awaiting next
2820 /// clustering cycle" empty state.
2821 #[prost(bool, tag="4")]
2822 pub insufficient_history: bool,
2823}
2824// ─── Short-code messages ────────────────────────────────────────────────────
2825
2826/// Request to resolve a campaign's short-code, lazily generating one on
2827/// first call. Used by internal-service callers (the dispatch layer)
2828/// when assembling a third-party-channel deeplink:
2829/// `links.pidgr.com/c/{short_code}?t={token}`.
2830#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2831pub struct ResolveOrCreateShortCodeRequest {
2832 /// The campaign whose short-code is being resolved.
2833 /// Constraints: Required, must be a UUID and exist within the caller's organization.
2834 #[prost(string, tag="1")]
2835 pub campaign_id: ::prost::alloc::string::String,
2836}
2837/// Response carrying the resolved short-code. The same campaign always
2838/// resolves to the same code for its lifetime; the value is safe to
2839/// cache by the caller.
2840#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2841pub struct ResolveOrCreateShortCodeResponse {
2842 /// 8-character base62 short-code stable for the campaign's lifetime.
2843 #[prost(string, tag="1")]
2844 pub short_code: ::prost::alloc::string::String,
2845}
2846/// Request to look up a campaign by its public short-code. Called by the
2847/// native app when the recipient taps a third-party-channel deeplink and
2848/// the URL handler needs to route to the right campaign card. Designed to
2849/// be safe to call without authentication — the response carries no PII
2850/// and only enough context for the app to route correctly and show org
2851/// branding before the auth gate.
2852#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2853pub struct GetCampaignByShortCodeRequest {
2854 /// The 8-character short-code from the deeplink path.
2855 /// Constraints: Required, exactly 8 base62 characters.
2856 #[prost(string, tag="1")]
2857 pub short_code: ::prost::alloc::string::String,
2858}
2859/// Response carrying the minimum metadata the native app needs to route
2860/// the deeplink. Subject is the campaign's title text (already visible
2861/// in the recipient's inbox after dispatch — no new PII exposure). Body
2862/// content, audience size, delivery status and any other operational
2863/// fields are NOT included; the app fetches those via authenticated
2864/// `GetCampaign` after the recipient signs in.
2865#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2866pub struct GetCampaignByShortCodeResponse {
2867 /// Campaign UUID — the app uses this for the authenticated `GetCampaign`
2868 /// follow-up after the deeplink token validates.
2869 #[prost(string, tag="1")]
2870 pub campaign_id: ::prost::alloc::string::String,
2871 /// Organization UUID owning the campaign — lets the app pick the
2872 /// correct SSO / sign-in flow when the recipient is logged out.
2873 #[prost(string, tag="2")]
2874 pub org_id: ::prost::alloc::string::String,
2875 /// Display name of the organization for sign-in branding ("Sign in to
2876 /// Acme Inc to view this campaign"). Public information; the
2877 /// organization's profile already exposes it elsewhere.
2878 #[prost(string, tag="3")]
2879 pub organization_name: ::prost::alloc::string::String,
2880 /// Campaign subject (title). Same string the recipient already saw in
2881 /// their inbox; included so the deeplink interstitial can show
2882 /// "Acme Inc — All-hands Q3" before the auth gate.
2883 #[prost(string, tag="4")]
2884 pub subject: ::prost::alloc::string::String,
2885}
2886// ─── Messages ───────────────────────────────────────────────────────────────
2887
2888/// A registered device that can receive push notifications.
2889/// INTERNAL: This message is for server-side use only. Use DeviceSummary for API responses.
2890#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2891pub struct Device {
2892 /// Unique identifier for this device.
2893 /// Constraints: UUID format (36 characters).
2894 #[prost(string, tag="1")]
2895 pub device_id: ::prost::alloc::string::String,
2896 /// ID of the user who owns this device.
2897 /// Constraints: UUID format (36 characters).
2898 #[prost(string, tag="2")]
2899 pub user_id: ::prost::alloc::string::String,
2900 /// Mobile platform (iOS or Android).
2901 #[prost(enumeration="Platform", tag="3")]
2902 pub platform: i32,
2903 /// Push token used to send notifications to this device.
2904 #[prost(string, tag="4")]
2905 pub push_token: ::prost::alloc::string::String,
2906 /// Whether the device is currently active and eligible for push delivery.
2907 #[prost(bool, tag="5")]
2908 pub active: bool,
2909 /// Timestamp of the last activity from this device.
2910 #[prost(message, optional, tag="6")]
2911 pub last_seen: ::core::option::Option<::prost_types::Timestamp>,
2912 /// Timestamp when the device was first registered.
2913 #[prost(message, optional, tag="7")]
2914 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
2915}
2916/// A device summary safe for API responses — excludes sensitive push_token.
2917#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2918pub struct DeviceSummary {
2919 /// Unique identifier for this device.
2920 #[prost(string, tag="1")]
2921 pub device_id: ::prost::alloc::string::String,
2922 /// ID of the user who owns this device.
2923 #[prost(string, tag="2")]
2924 pub user_id: ::prost::alloc::string::String,
2925 /// Mobile platform (iOS or Android).
2926 #[prost(enumeration="Platform", tag="3")]
2927 pub platform: i32,
2928 /// Whether the device is currently active and eligible for push delivery.
2929 #[prost(bool, tag="4")]
2930 pub active: bool,
2931 /// Timestamp of the last activity from this device.
2932 #[prost(message, optional, tag="5")]
2933 pub last_seen: ::core::option::Option<::prost_types::Timestamp>,
2934 /// Timestamp when the device was first registered.
2935 #[prost(message, optional, tag="6")]
2936 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
2937}
2938/// Request to register a device for push notifications.
2939#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2940pub struct RegisterRequest {
2941 /// Client-generated unique device identifier.
2942 /// Constraints: UUID format (36 characters).
2943 #[prost(string, tag="1")]
2944 pub device_id: ::prost::alloc::string::String,
2945 /// Mobile platform of the device.
2946 #[prost(enumeration="Platform", tag="2")]
2947 pub platform: i32,
2948 /// Push token obtained from the push notification provider on the client.
2949 /// Constraints: Max length 4096 characters.
2950 #[prost(string, tag="3")]
2951 pub push_token: ::prost::alloc::string::String,
2952}
2953/// Response after registering a device.
2954#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2955pub struct RegisterResponse {
2956 /// The registered device summary (excludes push_token).
2957 #[prost(message, optional, tag="1")]
2958 pub device: ::core::option::Option<DeviceSummary>,
2959}
2960/// Request to deactivate a device, stopping push notifications.
2961#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2962pub struct DeactivateRequest {
2963 /// ID of the device to deactivate.
2964 /// Constraints: UUID format (36 characters).
2965 #[prost(string, tag="1")]
2966 pub device_id: ::prost::alloc::string::String,
2967}
2968/// Response after deactivating a device.
2969#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
2970pub struct DeactivateResponse {
2971 /// Whether the device was successfully deactivated.
2972 #[prost(bool, tag="1")]
2973 pub success: bool,
2974}
2975/// Request to list all devices for the authenticated user.
2976#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
2977pub struct ListDevicesRequest {
2978}
2979/// Response containing all devices for the user.
2980#[derive(Clone, PartialEq, ::prost::Message)]
2981pub struct ListDevicesResponse {
2982 /// List of devices registered to the authenticated user.
2983 #[prost(message, repeated, tag="1")]
2984 pub devices: ::prost::alloc::vec::Vec<DeviceSummary>,
2985}
2986/// Request to list devices for a specific member (admin use).
2987#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
2988pub struct ListMemberDevicesRequest {
2989 /// ID of the user whose devices to list.
2990 /// Constraints: UUID format (36 characters).
2991 #[prost(string, tag="1")]
2992 pub user_id: ::prost::alloc::string::String,
2993}
2994/// Response containing all devices for the specified member.
2995#[derive(Clone, PartialEq, ::prost::Message)]
2996pub struct ListMemberDevicesResponse {
2997 /// List of devices registered to the specified user.
2998 #[prost(message, repeated, tag="1")]
2999 pub devices: ::prost::alloc::vec::Vec<DeviceSummary>,
3000}
3001// ─── Messages ───────────────────────────────────────────────────────────────
3002
3003/// User-configurable platform settings that apply across all clients.
3004/// All fields use their UNSPECIFIED/zero value to mean "no change" in updates.
3005#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3006pub struct UserSettings {
3007 /// Preferred color scheme for the UI.
3008 #[prost(enumeration="ThemePreference", tag="1")]
3009 pub theme_preference: i32,
3010 /// User's preferred language for the UI and push notifications.
3011 /// Empty string means "use organization default" or "auto-detect".
3012 /// Valid values: en, es, pt-BR, zh, ja.
3013 #[prost(string, tag="2")]
3014 pub preferred_locale: ::prost::alloc::string::String,
3015}
3016/// Structured profile attributes for a user within an organization.
3017/// Populated through admin invitation, mobile onboarding, or SSO attribute sync.
3018#[derive(Clone, PartialEq, ::prost::Message)]
3019pub struct UserProfile {
3020 /// User's given name.
3021 /// Constraints: Max length 200 characters.
3022 #[prost(string, tag="1")]
3023 pub first_name: ::prost::alloc::string::String,
3024 /// User's family name.
3025 /// Constraints: Max length 200 characters.
3026 #[prost(string, tag="2")]
3027 pub last_name: ::prost::alloc::string::String,
3028 /// Department or team within the organization.
3029 /// Constraints: Max length 200 characters.
3030 #[prost(string, tag="3")]
3031 pub department: ::prost::alloc::string::String,
3032 /// Job title.
3033 /// Constraints: Max length 200 characters.
3034 #[prost(string, tag="4")]
3035 pub title: ::prost::alloc::string::String,
3036 /// Phone number.
3037 /// Constraints: Max length 200 characters.
3038 #[prost(string, tag="5")]
3039 pub phone: ::prost::alloc::string::String,
3040 /// Office or geographic location.
3041 /// Constraints: Max length 200 characters.
3042 #[prost(string, tag="6")]
3043 pub location: ::prost::alloc::string::String,
3044 /// Organization-specific employee identifier.
3045 /// Constraints: Max length 200 characters.
3046 #[prost(string, tag="7")]
3047 pub employee_id: ::prost::alloc::string::String,
3048 /// Display name of the user's direct manager.
3049 /// Constraints: Max length 200 characters.
3050 #[prost(string, tag="8")]
3051 pub manager_name: ::prost::alloc::string::String,
3052 /// Employment start date in ISO 8601 format (YYYY-MM-DD).
3053 /// Constraints: Max length 200 characters.
3054 #[prost(string, tag="9")]
3055 pub start_date: ::prost::alloc::string::String,
3056 /// Organization-defined custom attributes for fields not covered by the fixed schema.
3057 /// Constraints: Max 50 entries. Key max length 100 characters, value max length 1000 characters.
3058 #[prost(map="string, string", tag="10")]
3059 pub custom_attributes: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
3060 /// UUID of the user's direct manager within the same organization.
3061 /// Populated from SCIM enterprise extension (manager.value), manual admin
3062 /// assignment, or SSO attribute mapping. Empty if not set.
3063 #[prost(string, tag="11")]
3064 pub manager_id: ::prost::alloc::string::String,
3065}
3066/// A user within an organization.
3067#[derive(Clone, PartialEq, ::prost::Message)]
3068pub struct User {
3069 /// Unique identifier for the user (internal platform UUID, not identity provider subject ID).
3070 #[prost(string, tag="1")]
3071 pub id: ::prost::alloc::string::String,
3072 /// User's email address.
3073 /// Constraints: Max length 254 characters (RFC 5321).
3074 #[prost(string, tag="2")]
3075 pub email: ::prost::alloc::string::String,
3076 /// User's display name.
3077 /// Constraints: Max length 200 characters.
3078 #[prost(string, tag="3")]
3079 pub name: ::prost::alloc::string::String,
3080 /// Current account status.
3081 #[prost(enumeration="UserStatus", tag="5")]
3082 pub status: i32,
3083 /// Timestamp when the user was created.
3084 #[prost(message, optional, tag="6")]
3085 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
3086 /// The user's role with its permission set.
3087 #[prost(message, optional, tag="7")]
3088 pub role: ::core::option::Option<Role>,
3089 /// ID of the user's role (for assignment operations).
3090 #[prost(string, tag="8")]
3091 pub role_id: ::prost::alloc::string::String,
3092 /// Structured profile attributes (department, title, etc.).
3093 /// May be empty if the user has not completed their profile.
3094 #[prost(message, optional, tag="9")]
3095 pub profile: ::core::option::Option<UserProfile>,
3096 /// Whether data processing is restricted for this user (GDPR Art. 18).
3097 /// When true, the user is excluded from campaign audiences by default.
3098 #[prost(bool, tag="10")]
3099 pub processing_restricted: bool,
3100 /// Data governance region override. Empty string means "inherit from org default".
3101 /// Valid values: EU, LATAM, BR, APAC, US.
3102 #[prost(string, tag="11")]
3103 pub data_governance_region: ::prost::alloc::string::String,
3104}
3105// ─── Enums ──────────────────────────────────────────────────────────────────
3106
3107/// Lifecycle status of a user account.
3108#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
3109#[repr(i32)]
3110pub enum UserStatus {
3111 /// Default value; not a valid status.
3112 Unspecified = 0,
3113 /// User has been invited but has not completed onboarding.
3114 Invited = 1,
3115 /// User is active and can receive messages.
3116 Active = 2,
3117 /// User has been deactivated and will not receive messages.
3118 Deactivated = 3,
3119}
3120impl UserStatus {
3121 /// String value of the enum field names used in the ProtoBuf definition.
3122 ///
3123 /// The values are not transformed in any way and thus are considered stable
3124 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
3125 pub fn as_str_name(&self) -> &'static str {
3126 match self {
3127 Self::Unspecified => "USER_STATUS_UNSPECIFIED",
3128 Self::Invited => "USER_STATUS_INVITED",
3129 Self::Active => "USER_STATUS_ACTIVE",
3130 Self::Deactivated => "USER_STATUS_DEACTIVATED",
3131 }
3132 }
3133 /// Creates an enum from field names used in the ProtoBuf definition.
3134 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
3135 match value {
3136 "USER_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
3137 "USER_STATUS_INVITED" => Some(Self::Invited),
3138 "USER_STATUS_ACTIVE" => Some(Self::Active),
3139 "USER_STATUS_DEACTIVATED" => Some(Self::Deactivated),
3140 _ => None,
3141 }
3142 }
3143}
3144/// User's preferred color scheme.
3145#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
3146#[repr(i32)]
3147pub enum ThemePreference {
3148 /// Default value; treated as SYSTEM when reading, "no change" when updating.
3149 Unspecified = 0,
3150 /// Always use light mode regardless of system setting.
3151 Light = 1,
3152 /// Always use dark mode regardless of system setting.
3153 Dark = 2,
3154 /// Follow the operating system or browser preference.
3155 System = 3,
3156}
3157impl ThemePreference {
3158 /// String value of the enum field names used in the ProtoBuf definition.
3159 ///
3160 /// The values are not transformed in any way and thus are considered stable
3161 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
3162 pub fn as_str_name(&self) -> &'static str {
3163 match self {
3164 Self::Unspecified => "THEME_PREFERENCE_UNSPECIFIED",
3165 Self::Light => "THEME_PREFERENCE_LIGHT",
3166 Self::Dark => "THEME_PREFERENCE_DARK",
3167 Self::System => "THEME_PREFERENCE_SYSTEM",
3168 }
3169 }
3170 /// Creates an enum from field names used in the ProtoBuf definition.
3171 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
3172 match value {
3173 "THEME_PREFERENCE_UNSPECIFIED" => Some(Self::Unspecified),
3174 "THEME_PREFERENCE_LIGHT" => Some(Self::Light),
3175 "THEME_PREFERENCE_DARK" => Some(Self::Dark),
3176 "THEME_PREFERENCE_SYSTEM" => Some(Self::System),
3177 _ => None,
3178 }
3179 }
3180}
3181// ─── Messages ───────────────────────────────────────────────────────────────
3182
3183/// A named collection of users within an organization, used for campaign
3184/// audience targeting (recipient groups).
3185#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3186pub struct Group {
3187 /// Unique identifier for the group.
3188 #[prost(string, tag="1")]
3189 pub id: ::prost::alloc::string::String,
3190 /// Human-readable display name (unique within the organization).
3191 /// Constraints: Max length 200 characters.
3192 #[prost(string, tag="2")]
3193 pub name: ::prost::alloc::string::String,
3194 /// Optional description of the group's purpose.
3195 /// Constraints: Max length 1000 characters.
3196 #[prost(string, tag="3")]
3197 pub description: ::prost::alloc::string::String,
3198 /// Number of users currently in the group.
3199 #[prost(int32, tag="4")]
3200 pub member_count: i32,
3201 /// Timestamp when the group was created.
3202 #[prost(message, optional, tag="5")]
3203 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
3204 /// Timestamp when the group was last updated.
3205 #[prost(message, optional, tag="6")]
3206 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
3207 /// Whether this is the organization's default group (cannot be deleted or renamed).
3208 #[prost(bool, tag="7")]
3209 pub is_default: bool,
3210 /// ID of the user who created this group. Empty for system-seeded defaults.
3211 #[prost(string, tag="8")]
3212 pub created_by: ::prost::alloc::string::String,
3213}
3214/// Request to create a new group.
3215#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3216pub struct CreateGroupRequest {
3217 /// Display name for the group. Required.
3218 /// Constraints: Max length 200 characters.
3219 #[prost(string, tag="1")]
3220 pub name: ::prost::alloc::string::String,
3221 /// Optional description.
3222 /// Constraints: Max length 1000 characters.
3223 #[prost(string, tag="2")]
3224 pub description: ::prost::alloc::string::String,
3225}
3226/// Response after creating a group.
3227#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3228pub struct CreateGroupResponse {
3229 /// The newly created group.
3230 #[prost(message, optional, tag="1")]
3231 pub group: ::core::option::Option<Group>,
3232}
3233/// Request to retrieve a group by ID.
3234#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3235pub struct GetGroupRequest {
3236 /// ID of the group to retrieve. Required.
3237 #[prost(string, tag="1")]
3238 pub group_id: ::prost::alloc::string::String,
3239}
3240/// Response containing the requested group.
3241#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3242pub struct GetGroupResponse {
3243 /// The requested group.
3244 #[prost(message, optional, tag="1")]
3245 pub group: ::core::option::Option<Group>,
3246}
3247/// Request to list groups in the organization with pagination.
3248#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3249pub struct ListGroupsRequest {
3250 /// Pagination parameters.
3251 #[prost(message, optional, tag="1")]
3252 pub pagination: ::core::option::Option<Pagination>,
3253}
3254/// Response containing a page of groups.
3255#[derive(Clone, PartialEq, ::prost::Message)]
3256pub struct ListGroupsResponse {
3257 /// Groups in this page.
3258 #[prost(message, repeated, tag="1")]
3259 pub groups: ::prost::alloc::vec::Vec<Group>,
3260 /// Pagination metadata for fetching subsequent pages.
3261 #[prost(message, optional, tag="2")]
3262 pub pagination_meta: ::core::option::Option<PaginationMeta>,
3263}
3264/// Request to update a group's name and/or description.
3265#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3266pub struct UpdateGroupRequest {
3267 /// ID of the group to update. Required.
3268 #[prost(string, tag="1")]
3269 pub group_id: ::prost::alloc::string::String,
3270 /// New display name. If empty, the name is not changed.
3271 /// Default groups cannot be renamed.
3272 /// Constraints: Max length 200 characters.
3273 #[prost(string, tag="2")]
3274 pub name: ::prost::alloc::string::String,
3275 /// New description. If empty, the description is not changed.
3276 /// Constraints: Max length 1000 characters.
3277 #[prost(string, tag="3")]
3278 pub description: ::prost::alloc::string::String,
3279}
3280/// Response after updating a group.
3281#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3282pub struct UpdateGroupResponse {
3283 /// The updated group.
3284 #[prost(message, optional, tag="1")]
3285 pub group: ::core::option::Option<Group>,
3286}
3287/// Request to delete a group.
3288#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3289pub struct DeleteGroupRequest {
3290 /// ID of the group to delete. Required.
3291 /// Default groups cannot be deleted.
3292 #[prost(string, tag="1")]
3293 pub group_id: ::prost::alloc::string::String,
3294}
3295/// Response after deleting a group.
3296#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3297pub struct DeleteGroupResponse {
3298}
3299/// Request to add users to a group.
3300#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3301pub struct AddGroupMembersRequest {
3302 /// ID of the group to add members to. Required.
3303 #[prost(string, tag="1")]
3304 pub group_id: ::prost::alloc::string::String,
3305 /// IDs of users to add. Must belong to the same organization.
3306 /// Adding an existing member is a no-op (idempotent).
3307 /// Constraints: Max 100 user IDs per request.
3308 #[prost(string, repeated, tag="2")]
3309 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
3310}
3311/// Response after adding group members.
3312#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3313pub struct AddGroupMembersResponse {
3314 /// The group with updated member_count.
3315 #[prost(message, optional, tag="1")]
3316 pub group: ::core::option::Option<Group>,
3317}
3318/// Request to remove users from a group.
3319#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3320pub struct RemoveGroupMembersRequest {
3321 /// ID of the group to remove members from. Required.
3322 #[prost(string, tag="1")]
3323 pub group_id: ::prost::alloc::string::String,
3324 /// IDs of users to remove. Removing a non-member is a no-op (idempotent).
3325 /// Constraints: Max 100 user IDs per request.
3326 #[prost(string, repeated, tag="2")]
3327 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
3328}
3329/// Response after removing group members.
3330#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3331pub struct RemoveGroupMembersResponse {
3332 /// The group with updated member_count.
3333 #[prost(message, optional, tag="1")]
3334 pub group: ::core::option::Option<Group>,
3335}
3336/// Request to list members of a group with pagination.
3337#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3338pub struct ListGroupMembersRequest {
3339 /// ID of the group whose members to list. Required.
3340 #[prost(string, tag="1")]
3341 pub group_id: ::prost::alloc::string::String,
3342 /// Pagination parameters.
3343 #[prost(message, optional, tag="2")]
3344 pub pagination: ::core::option::Option<Pagination>,
3345}
3346/// Response containing a page of group members.
3347#[derive(Clone, PartialEq, ::prost::Message)]
3348pub struct ListGroupMembersResponse {
3349 /// Users in this page.
3350 #[prost(message, repeated, tag="1")]
3351 pub users: ::prost::alloc::vec::Vec<User>,
3352 /// Pagination metadata for fetching subsequent pages.
3353 #[prost(message, optional, tag="2")]
3354 pub pagination_meta: ::core::option::Option<PaginationMeta>,
3355}
3356/// A group membership entry for batch lookups.
3357#[derive(Clone, PartialEq, ::prost::Message)]
3358pub struct UserGroupMembership {
3359 /// ID of the user.
3360 #[prost(string, tag="1")]
3361 pub user_id: ::prost::alloc::string::String,
3362 /// Groups the user belongs to.
3363 #[prost(message, repeated, tag="2")]
3364 pub groups: ::prost::alloc::vec::Vec<Group>,
3365}
3366/// Request to get group memberships for a batch of users.
3367#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3368pub struct GetUserGroupMembershipsRequest {
3369 /// IDs of users to look up. Required.
3370 /// Constraints: Max 200 user IDs per request.
3371 #[prost(string, repeated, tag="1")]
3372 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
3373}
3374/// Response containing group memberships for the requested users.
3375#[derive(Clone, PartialEq, ::prost::Message)]
3376pub struct GetUserGroupMembershipsResponse {
3377 /// Group memberships per user. Only users with at least one group are included.
3378 #[prost(message, repeated, tag="1")]
3379 pub memberships: ::prost::alloc::vec::Vec<UserGroupMembership>,
3380}
3381// ─── Messages ───────────────────────────────────────────────────────────────
3382
3383/// A single touch event captured from the mobile app.
3384#[derive(Clone, PartialEq, ::prost::Message)]
3385pub struct TouchEvent {
3386 /// Screen name from React Navigation route.
3387 /// Constraints: Max length 200 characters.
3388 #[prost(string, tag="1")]
3389 pub screen_name: ::prost::alloc::string::String,
3390 /// Horizontal coordinate as a percentage of screen width (0.0–1.0).
3391 /// Constraints: Range 0.0 to 1.0 inclusive.
3392 #[prost(float, tag="2")]
3393 pub x_pct: f32,
3394 /// Vertical coordinate as a percentage of screen height (0.0–1.0).
3395 /// Constraints: Range 0.0 to 1.0 inclusive.
3396 #[prost(float, tag="3")]
3397 pub y_pct: f32,
3398 /// Type of touch event.
3399 #[prost(enumeration="TouchEventType", tag="4")]
3400 pub event_type: i32,
3401 /// Screen width in device pixels at the time of capture.
3402 #[prost(int32, tag="5")]
3403 pub screen_width: i32,
3404 /// Screen height in device pixels at the time of capture.
3405 #[prost(int32, tag="6")]
3406 pub screen_height: i32,
3407 /// Client-side timestamp when the touch occurred.
3408 #[prost(message, optional, tag="7")]
3409 pub client_timestamp: ::core::option::Option<::prost_types::Timestamp>,
3410 /// Campaign ID if the touch occurred during a campaign message view.
3411 /// Empty string for organic (non-campaign) navigation.
3412 #[prost(string, tag="8")]
3413 pub campaign_id: ::prost::alloc::string::String,
3414}
3415/// Request to ingest a batch of touch events from the mobile app.
3416#[derive(Clone, PartialEq, ::prost::Message)]
3417pub struct IngestTouchEventsRequest {
3418 /// Batch of touch events to ingest.
3419 /// Constraints: Max 100 events per batch.
3420 #[prost(message, repeated, tag="1")]
3421 pub events: ::prost::alloc::vec::Vec<TouchEvent>,
3422}
3423/// Response after ingesting touch events.
3424#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3425pub struct IngestTouchEventsResponse {
3426 /// Number of events successfully ingested.
3427 #[prost(int32, tag="1")]
3428 pub ingested_count: i32,
3429}
3430/// A single aggregated data point in a heatmap grid cell.
3431#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3432pub struct HeatmapDataPoint {
3433 /// Grid cell horizontal center as a percentage (0.0–1.0).
3434 #[prost(float, tag="1")]
3435 pub x_pct: f32,
3436 /// Grid cell vertical center as a percentage (0.0–1.0).
3437 #[prost(float, tag="2")]
3438 pub y_pct: f32,
3439 /// Aggregated value for this cell (count, median, or z-score depending on mode).
3440 #[prost(float, tag="3")]
3441 pub value: f32,
3442}
3443/// Request to query aggregated heatmap data for a screen.
3444#[derive(Clone, PartialEq, ::prost::Message)]
3445pub struct QueryHeatmapDataRequest {
3446 /// Screen name to query.
3447 /// Constraints: Max length 200 characters.
3448 #[prost(string, tag="1")]
3449 pub screen_name: ::prost::alloc::string::String,
3450 /// Start of the time range filter (inclusive).
3451 #[prost(message, optional, tag="2")]
3452 pub date_from: ::core::option::Option<::prost_types::Timestamp>,
3453 /// End of the time range filter (inclusive).
3454 #[prost(message, optional, tag="3")]
3455 pub date_to: ::core::option::Option<::prost_types::Timestamp>,
3456 /// Optional: filter by campaign ID.
3457 /// Constraints: UUID format (36 characters).
3458 #[prost(string, tag="4")]
3459 pub campaign_id: ::prost::alloc::string::String,
3460 /// Grid resolution for coordinate rounding. Default: 0.02 (50×50 grid).
3461 /// Constraints: Range 0.005 to 0.1.
3462 #[prost(float, tag="6")]
3463 pub grid_resolution: f32,
3464 /// Aggregation mode (TOTAL or MEDIAN).
3465 #[prost(enumeration="HeatmapMode", tag="7")]
3466 pub mode: i32,
3467 /// Optional: filter by event types. Empty list means all types.
3468 #[prost(enumeration="TouchEventType", repeated, tag="8")]
3469 pub event_types: ::prost::alloc::vec::Vec<i32>,
3470}
3471/// Response containing aggregated heatmap data.
3472#[derive(Clone, PartialEq, ::prost::Message)]
3473pub struct QueryHeatmapDataResponse {
3474 /// Aggregated data points for heatmap rendering.
3475 #[prost(message, repeated, tag="1")]
3476 pub data_points: ::prost::alloc::vec::Vec<HeatmapDataPoint>,
3477 /// URL to a mobile-captured screenshot for this screen, if available.
3478 /// Empty string when no screenshot exists.
3479 #[prost(string, tag="3")]
3480 pub screenshot_url: ::prost::alloc::string::String,
3481 /// Whether per-cohort bucket breakdowns are available (k >= 5).
3482 #[prost(bool, tag="4")]
3483 pub cohort_enabled: bool,
3484}
3485/// Request to upload a screenshot captured from the mobile app.
3486#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3487pub struct UploadScreenshotRequest {
3488 /// Screen name matching React Navigation route (e.g. "MessageDetail::<campaign_uuid>").
3489 /// Constraints: Max length 200 characters.
3490 #[prost(string, tag="1")]
3491 pub screen_name: ::prost::alloc::string::String,
3492 /// App version that captured the screenshot (e.g. "1.15.0").
3493 #[prost(string, tag="2")]
3494 pub app_version: ::prost::alloc::string::String,
3495 /// PNG image data.
3496 /// Constraints: Max 512KB.
3497 #[prost(bytes="vec", tag="3")]
3498 pub image_data: ::prost::alloc::vec::Vec<u8>,
3499}
3500/// Response after uploading a screenshot.
3501#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3502pub struct UploadScreenshotResponse {
3503 /// S3 URL where the screenshot was stored.
3504 #[prost(string, tag="1")]
3505 pub url: ::prost::alloc::string::String,
3506}
3507/// A screen screenshot stored as a static asset.
3508#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3509pub struct ScreenScreenshot {
3510 /// Screen name matching React Navigation route.
3511 #[prost(string, tag="1")]
3512 pub screen_name: ::prost::alloc::string::String,
3513 /// S3 URL to the screenshot image.
3514 #[prost(string, tag="2")]
3515 pub url: ::prost::alloc::string::String,
3516 /// App version this screenshot corresponds to.
3517 #[prost(string, tag="3")]
3518 pub app_version: ::prost::alloc::string::String,
3519}
3520/// Request to list available screen screenshots.
3521#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3522pub struct ListScreenshotsRequest {
3523}
3524/// Response containing available screen screenshots.
3525#[derive(Clone, PartialEq, ::prost::Message)]
3526pub struct ListScreenshotsResponse {
3527 /// Available screen screenshots with their URLs and versions.
3528 #[prost(message, repeated, tag="1")]
3529 pub screenshots: ::prost::alloc::vec::Vec<ScreenScreenshot>,
3530}
3531// ─── Enums ──────────────────────────────────────────────────────────────────
3532
3533/// Type of touch event captured on the mobile app.
3534#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
3535#[repr(i32)]
3536pub enum TouchEventType {
3537 /// Default value; not a valid event type.
3538 Unspecified = 0,
3539 /// A single tap on the screen.
3540 Tap = 1,
3541 /// A long press (held for 500ms+).
3542 LongPress = 2,
3543 /// A periodic scroll position sample (viewport midpoint every 2s).
3544 Scroll = 3,
3545 /// The user tapped an action button (e.g. "Acknowledge").
3546 ActionClick = 4,
3547}
3548impl TouchEventType {
3549 /// String value of the enum field names used in the ProtoBuf definition.
3550 ///
3551 /// The values are not transformed in any way and thus are considered stable
3552 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
3553 pub fn as_str_name(&self) -> &'static str {
3554 match self {
3555 Self::Unspecified => "TOUCH_EVENT_TYPE_UNSPECIFIED",
3556 Self::Tap => "TOUCH_EVENT_TYPE_TAP",
3557 Self::LongPress => "TOUCH_EVENT_TYPE_LONG_PRESS",
3558 Self::Scroll => "TOUCH_EVENT_TYPE_SCROLL",
3559 Self::ActionClick => "TOUCH_EVENT_TYPE_ACTION_CLICK",
3560 }
3561 }
3562 /// Creates an enum from field names used in the ProtoBuf definition.
3563 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
3564 match value {
3565 "TOUCH_EVENT_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
3566 "TOUCH_EVENT_TYPE_TAP" => Some(Self::Tap),
3567 "TOUCH_EVENT_TYPE_LONG_PRESS" => Some(Self::LongPress),
3568 "TOUCH_EVENT_TYPE_SCROLL" => Some(Self::Scroll),
3569 "TOUCH_EVENT_TYPE_ACTION_CLICK" => Some(Self::ActionClick),
3570 _ => None,
3571 }
3572 }
3573}
3574/// Aggregation mode for heatmap data queries.
3575#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
3576#[repr(i32)]
3577pub enum HeatmapMode {
3578 /// Default value; not a valid mode.
3579 Unspecified = 0,
3580 /// Sum of all cohort buckets' touches per grid cell (default).
3581 Total = 1,
3582 /// Median touch count per grid cell across cohort buckets.
3583 Median = 2,
3584}
3585impl HeatmapMode {
3586 /// String value of the enum field names used in the ProtoBuf definition.
3587 ///
3588 /// The values are not transformed in any way and thus are considered stable
3589 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
3590 pub fn as_str_name(&self) -> &'static str {
3591 match self {
3592 Self::Unspecified => "HEATMAP_MODE_UNSPECIFIED",
3593 Self::Total => "HEATMAP_MODE_TOTAL",
3594 Self::Median => "HEATMAP_MODE_MEDIAN",
3595 }
3596 }
3597 /// Creates an enum from field names used in the ProtoBuf definition.
3598 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
3599 match value {
3600 "HEATMAP_MODE_UNSPECIFIED" => Some(Self::Unspecified),
3601 "HEATMAP_MODE_TOTAL" => Some(Self::Total),
3602 "HEATMAP_MODE_MEDIAN" => Some(Self::Median),
3603 _ => None,
3604 }
3605 }
3606}
3607// ─── Messages ───────────────────────────────────────────────────────────────
3608
3609/// A single entry in a user's inbox, combining a message with its delivery state.
3610#[derive(Clone, PartialEq, ::prost::Message)]
3611pub struct InboxEntry {
3612 /// ID of the delivery record for this inbox entry.
3613 /// Constraints: UUID format (36 characters).
3614 #[prost(string, tag="1")]
3615 pub delivery_id: ::prost::alloc::string::String,
3616 /// The fully rendered message content.
3617 #[prost(message, optional, tag="2")]
3618 pub message: ::core::option::Option<Message>,
3619 /// Current delivery status (e.g. DELIVERED, ACKNOWLEDGED).
3620 #[prost(enumeration="DeliveryStatus", tag="3")]
3621 pub status: i32,
3622 /// Whether the user has read this message.
3623 #[prost(bool, tag="4")]
3624 pub read: bool,
3625 /// Timestamp when the message was received in the inbox.
3626 #[prost(message, optional, tag="5")]
3627 pub received_at: ::core::option::Option<::prost_types::Timestamp>,
3628 /// Discriminator: PRIMARY for normal deliveries, ESCALATION for delivery-grade
3629 /// escalations. Mirrors Delivery.kind so inbox-sync clients can branch on the
3630 /// same dimension as listDeliveries clients.
3631 #[prost(enumeration="delivery::Kind", tag="6")]
3632 pub kind: i32,
3633 /// For ESCALATION entries, the UUID of the unacked delivery that triggered this
3634 /// entry. Empty for PRIMARY entries.
3635 #[prost(string, tag="7")]
3636 pub parent_delivery_id: ::prost::alloc::string::String,
3637 /// The locale the body actually rendered in after fallback resolution. Empty
3638 /// for legacy/PRIMARY entries.
3639 #[prost(string, tag="8")]
3640 pub rendered_locale: ::prost::alloc::string::String,
3641 /// Optional out-of-band context mirrored from the underlying delivery.
3642 /// See `DeliveryMetadata` for which delivery kinds populate which fields.
3643 /// Empty for PRIMARY entries.
3644 #[prost(message, optional, tag="9")]
3645 pub metadata: ::core::option::Option<DeliveryMetadata>,
3646}
3647/// Request to sync inbox entries since a given timestamp.
3648#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3649pub struct SyncRequest {
3650 /// Fetch entries newer than this timestamp. Omit for initial sync.
3651 #[prost(message, optional, tag="1")]
3652 pub since: ::core::option::Option<::prost_types::Timestamp>,
3653 /// Maximum number of entries to return.
3654 /// Constraints: Valid range 1 to 200.
3655 #[prost(int32, tag="2")]
3656 pub limit: i32,
3657}
3658/// Response containing synced inbox entries.
3659#[derive(Clone, PartialEq, ::prost::Message)]
3660pub struct SyncResponse {
3661 /// Inbox entries newer than the requested timestamp.
3662 #[prost(message, repeated, tag="1")]
3663 pub entries: ::prost::alloc::vec::Vec<InboxEntry>,
3664 /// Cursor timestamp to use for the next sync call.
3665 #[prost(message, optional, tag="2")]
3666 pub next_since: ::core::option::Option<::prost_types::Timestamp>,
3667}
3668/// Request to mark a message as read.
3669#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3670pub struct MarkReadRequest {
3671 /// ID of the delivery to mark as read.
3672 /// Constraints: UUID format (36 characters).
3673 #[prost(string, tag="1")]
3674 pub delivery_id: ::prost::alloc::string::String,
3675}
3676/// Response after marking a message as read.
3677#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
3678pub struct MarkReadResponse {
3679 /// Whether the read status was successfully updated.
3680 #[prost(bool, tag="1")]
3681 pub success: bool,
3682}
3683/// Request to retrieve a single message by delivery ID.
3684#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3685pub struct GetMessageRequest {
3686 /// ID of the delivery to retrieve.
3687 /// Constraints: UUID format (36 characters).
3688 #[prost(string, tag="1")]
3689 pub delivery_id: ::prost::alloc::string::String,
3690}
3691/// Response containing the requested inbox entry.
3692#[derive(Clone, PartialEq, ::prost::Message)]
3693pub struct GetMessageResponse {
3694 /// The inbox entry for the requested delivery.
3695 #[prost(message, optional, tag="1")]
3696 pub entry: ::core::option::Option<InboxEntry>,
3697}
3698// ─── Messages ───────────────────────────────────────────────────────────────
3699
3700/// A behavioral archetype describing a cohort pattern (never an individual).
3701/// Derived from k-anonymized, DP-noised behavioral feature vectors.
3702#[derive(Clone, PartialEq, ::prost::Message)]
3703pub struct Archetype {
3704 /// Human-readable label (e.g., "Swift Acknowledger", "Thorough Reader").
3705 #[prost(string, tag="1")]
3706 pub label: ::prost::alloc::string::String,
3707 /// Description of the behavioral pattern this archetype represents.
3708 #[prost(string, tag="2")]
3709 pub description: ::prost::alloc::string::String,
3710 /// Proportion of the group that belongs to this archetype (0.0-1.0).
3711 #[prost(float, tag="3")]
3712 pub percentage: f32,
3713 /// Centroid of the behavioral feature vector for this archetype.
3714 /// Keys are stable dimension names from the feature extractor
3715 /// vocabulary (e.g., "tap_density", "engagement_depth",
3716 /// "scroll_velocity_p50", "idle_gap_p75"). Single-letter keys are
3717 /// reserved for backward compatibility with pre-v0.64 servers and
3718 /// SHALL be ignored by clients.
3719 #[prost(map="string, double", tag="4")]
3720 pub feature_centroid: ::std::collections::HashMap<::prost::alloc::string::String, f64>,
3721 /// Per-dimension distribution of the archetype's members. Lets the
3722 /// admin render percentile bands instead of single-point centroids.
3723 /// Absent until at least k members exist in the cluster. Keys mirror
3724 /// `feature_centroid` keys.
3725 #[prost(map="string, message", tag="5")]
3726 pub feature_breakdown: ::std::collections::HashMap<::prost::alloc::string::String, DimensionStats>,
3727 /// Tap density heatmap aggregated across sessions for this
3728 /// archetype. Cohort-level only — never per-session timing.
3729 /// Absent when fewer than k sessions have tap data.
3730 #[prost(message, optional, tag="6")]
3731 pub tap_heatmap: ::core::option::Option<TapHeatmap>,
3732 /// Forecast of cluster share at fixed horizons (7/14/30/90 days).
3733 /// Absent during cold start before historical clustering runs exist
3734 /// to extrapolate from.
3735 #[prost(message, optional, tag="7")]
3736 pub forecast: ::core::option::Option<ArchetypeForecast>,
3737 /// Sessions that sit at the median and quartiles of the archetype's
3738 /// centroid distance, ranked by distance. Bounded at three entries.
3739 /// Absent until at least 50 sessions have been scored.
3740 /// Sessions can come from any client that emits to ReplayService —
3741 /// mobile (iOS, Android) or desktop (macOS, Windows, Linux).
3742 #[prost(message, repeated, tag="8")]
3743 pub exemplar_sessions: ::prost::alloc::vec::Vec<ExemplarSession>,
3744 /// Per-screen dwell time distribution, derived from session replay.
3745 /// Absent when fewer than k sessions per screen exist.
3746 #[prost(message, optional, tag="9")]
3747 pub screen_dwell: ::core::option::Option<ScreenDwell>,
3748 /// End-to-end response latencies (push delivered → read → ack) for
3749 /// members of this archetype, as percentiles. Absent until at least
3750 /// k campaign deliveries have been recorded for this archetype.
3751 #[prost(message, optional, tag="10")]
3752 pub response_timeline: ::core::option::Option<ResponseTimeline>,
3753 /// Where this archetype came from. UNSPECIFIED on responses from
3754 /// pre-v0.81 servers; clients SHOULD treat UNSPECIFIED as ML for
3755 /// backward compatibility (provisional output is always labelled).
3756 #[prost(enumeration="ArchetypeSource", tag="11")]
3757 pub source: i32,
3758}
3759/// Per-dimension distribution stats for one feature dimension within
3760/// an archetype's cohort. All values are in the same units as
3761/// `Archetype.feature_centroid`. Used to render percentile bands on
3762/// the admin's behavioral profile panel.
3763#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3764pub struct DimensionStats {
3765 /// Centroid value (same as Archetype.feature_centroid\[key\]).
3766 #[prost(double, tag="1")]
3767 pub centroid: f64,
3768 /// 25th percentile across the archetype's members.
3769 #[prost(double, tag="2")]
3770 pub p25: f64,
3771 /// Median across the archetype's members.
3772 #[prost(double, tag="3")]
3773 pub p50: f64,
3774 /// 75th percentile across the archetype's members.
3775 #[prost(double, tag="4")]
3776 pub p75: f64,
3777 /// Median across the entire group (all archetypes), included so the
3778 /// admin can render "this archetype is X% above group median".
3779 #[prost(double, tag="5")]
3780 pub group_p50: f64,
3781}
3782/// A density grid of tap activity for one archetype, normalized to
3783/// \[0.0, 1.0\] where 1.0 is the hottest cell in the cohort. Cohort-
3784/// level only.
3785#[derive(Clone, PartialEq, ::prost::Message)]
3786pub struct TapHeatmap {
3787 /// Width of the density grid in cells.
3788 #[prost(int32, tag="1")]
3789 pub width: i32,
3790 /// Height of the density grid in cells.
3791 #[prost(int32, tag="2")]
3792 pub height: i32,
3793 /// Row-major density values, length must equal width*height. All in
3794 /// \[0.0, 1.0\].
3795 #[prost(double, repeated, tag="3")]
3796 pub values: ::prost::alloc::vec::Vec<f64>,
3797 /// Number of sessions aggregated. Always >= MinFeatureVectorsForClustering
3798 /// when the field is present.
3799 #[prost(int32, tag="4")]
3800 pub session_count: i32,
3801 /// Optional per-event-type breakdown. When present, the writer
3802 /// SHALL emit one entry for each event type in the source data
3803 /// (TAP, LONG_PRESS, SCROLL, ACTION_CLICK).
3804 #[prost(message, repeated, tag="5")]
3805 pub layers: ::prost::alloc::vec::Vec<TapHeatmapLayer>,
3806}
3807/// One per-event-type layer of a TapHeatmap.
3808#[derive(Clone, PartialEq, ::prost::Message)]
3809pub struct TapHeatmapLayer {
3810 /// Event type this layer represents (e.g., "TAP", "LONG_PRESS",
3811 /// "SCROLL", "ACTION_CLICK").
3812 #[prost(string, tag="1")]
3813 pub event_type: ::prost::alloc::string::String,
3814 /// Row-major density values, same dimensions as the parent
3815 /// TapHeatmap. Independently normalized to \[0.0, 1.0\].
3816 #[prost(double, repeated, tag="2")]
3817 pub values: ::prost::alloc::vec::Vec<f64>,
3818}
3819/// Predicted cluster share at fixed horizons with confidence bands.
3820#[derive(Clone, PartialEq, ::prost::Message)]
3821pub struct ArchetypeForecast {
3822 /// Horizons in increasing days. Always one entry each for 7, 14,
3823 /// 30, and 90 days when the field is present.
3824 #[prost(message, repeated, tag="1")]
3825 pub horizons: ::prost::alloc::vec::Vec<ForecastHorizon>,
3826}
3827/// Predicted share at one horizon with a 90% prediction interval.
3828#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3829pub struct ForecastHorizon {
3830 /// Horizon length in days (one of: 7, 14, 30, 90).
3831 #[prost(int32, tag="1")]
3832 pub days: i32,
3833 /// Predicted fraction of the group falling in this archetype at the
3834 /// horizon (0.0-1.0).
3835 #[prost(double, tag="2")]
3836 pub predicted_share: f64,
3837 /// 5th-percentile lower bound of the prediction interval.
3838 #[prost(double, tag="3")]
3839 pub lower: f64,
3840 /// 95th-percentile upper bound of the prediction interval.
3841 #[prost(double, tag="4")]
3842 pub upper: f64,
3843 /// Confidence in this horizon's prediction.
3844 #[prost(enumeration="ConfidenceLevel", tag="5")]
3845 pub confidence: i32,
3846}
3847/// Pointer to a representative session for one archetype, ranked by
3848/// distance to the archetype centroid.
3849#[derive(Clone, PartialEq, ::prost::Message)]
3850pub struct ExemplarSession {
3851 /// Session recording ID retrievable via ReplayService for the same
3852 /// org. Linkable from the admin regardless of originating platform.
3853 #[prost(string, tag="1")]
3854 pub session_id: ::prost::alloc::string::String,
3855 /// Quantile rank within the archetype: 25, 50, or 75. The writer
3856 /// emits at most one session per rank.
3857 #[prost(int32, tag="2")]
3858 pub rank: i32,
3859 /// L2 distance from the session's feature vector to the centroid.
3860 #[prost(double, tag="3")]
3861 pub distance: f64,
3862 /// Optional duration metadata for quick admin labelling.
3863 #[prost(int32, tag="4")]
3864 pub duration_seconds: i32,
3865 /// Optional platform identifier from the vocabulary
3866 /// {"ios", "android", "macos", "windows", "linux"}. The admin
3867 /// renders unknown values verbatim for forward compatibility.
3868 #[prost(string, tag="5")]
3869 pub platform: ::prost::alloc::string::String,
3870}
3871/// Per-screen dwell distribution within an archetype. Lets the admin
3872/// surface "this archetype lingers 8.2s on the Message Detail screen
3873/// vs 0.4s on the Inbox list".
3874#[derive(Clone, PartialEq, ::prost::Message)]
3875pub struct ScreenDwell {
3876 /// One entry per screen. Screens with fewer than k members in the
3877 /// archetype are dropped from the list (not marked as absent).
3878 #[prost(message, repeated, tag="1")]
3879 pub entries: ::prost::alloc::vec::Vec<ScreenDwellEntry>,
3880}
3881#[derive(Clone, PartialEq, ::prost::Message)]
3882pub struct ScreenDwellEntry {
3883 /// Stable screen identifier (e.g., "MessageDetail", "Inbox",
3884 /// "ProfileSettings"). Sourced from the same screen_name vocabulary
3885 /// used by heatmap_cells.
3886 #[prost(string, tag="1")]
3887 pub screen_name: ::prost::alloc::string::String,
3888 /// Median dwell time in seconds for this archetype on this screen.
3889 #[prost(double, tag="2")]
3890 pub median_seconds: f64,
3891 /// 75th-percentile dwell time in seconds.
3892 #[prost(double, tag="3")]
3893 pub p75_seconds: f64,
3894 /// Number of distinct sessions aggregated for this screen.
3895 #[prost(int32, tag="4")]
3896 pub session_count: i32,
3897}
3898/// End-to-end response latencies for members of one archetype, in
3899/// seconds. Each percentile is computed across all qualifying campaign
3900/// deliveries for the archetype's members within the rolling window.
3901#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3902pub struct ResponseTimeline {
3903 /// Time from `delivered_at` to `read_at`, in seconds.
3904 #[prost(message, optional, tag="1")]
3905 pub read_after_delivered: ::core::option::Option<LatencyPercentiles>,
3906 /// Time from `read_at` to `acknowledged_at`, in seconds. Only
3907 /// includes deliveries that were both read and acknowledged.
3908 #[prost(message, optional, tag="2")]
3909 pub ack_after_read: ::core::option::Option<LatencyPercentiles>,
3910 /// End-to-end time from `delivered_at` to `acknowledged_at`, in
3911 /// seconds. Only includes deliveries that were acknowledged.
3912 #[prost(message, optional, tag="3")]
3913 pub ack_after_delivered: ::core::option::Option<LatencyPercentiles>,
3914 /// Number of deliveries the timeline is computed over.
3915 #[prost(int32, tag="4")]
3916 pub delivery_count: i32,
3917}
3918/// Latency distribution stats. Values are in seconds.
3919#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3920pub struct LatencyPercentiles {
3921 #[prost(double, tag="1")]
3922 pub p50: f64,
3923 #[prost(double, tag="2")]
3924 pub p75: f64,
3925 #[prost(double, tag="3")]
3926 pub p95: f64,
3927}
3928/// A cohort-level prediction for campaign acknowledgment rate.
3929/// Never targets or scores individuals — always represents an audience aggregate.
3930#[derive(Clone, Copy, PartialEq, ::prost::Message)]
3931pub struct CohortPrediction {
3932 /// Predicted ACK rate for the audience (0.0-1.0).
3933 #[prost(float, tag="1")]
3934 pub predicted_ack_rate: f32,
3935 /// Lower bound of the confidence interval.
3936 #[prost(float, tag="2")]
3937 pub confidence_low: f32,
3938 /// Upper bound of the confidence interval.
3939 #[prost(float, tag="3")]
3940 pub confidence_high: f32,
3941 /// Confidence level based on available data volume.
3942 #[prost(enumeration="ConfidenceLevel", tag="4")]
3943 pub confidence_level: i32,
3944 /// Number of anonymous data points used for this prediction.
3945 #[prost(int32, tag="5")]
3946 pub data_point_count: i32,
3947}
3948/// Advisory information for campaign configuration, combining predictions and archetypes.
3949#[derive(Clone, PartialEq, ::prost::Message)]
3950pub struct CampaignAdvisory {
3951 /// Cohort-level ACK prediction for the target audience.
3952 #[prost(message, optional, tag="1")]
3953 pub predicted_ack: ::core::option::Option<CohortPrediction>,
3954 /// Suggested escalation delay in minutes based on historical cohort patterns.
3955 /// 0 if insufficient data.
3956 #[prost(int32, tag="2")]
3957 pub suggested_escalation_delay_minutes: i32,
3958 /// Behavioral archetypes for the target audience.
3959 #[prost(message, repeated, tag="3")]
3960 pub archetypes: ::prost::alloc::vec::Vec<Archetype>,
3961}
3962/// Request to retrieve behavioral archetypes for a group.
3963#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3964pub struct GetGroupArchetypesRequest {
3965 /// ID of the group to query archetypes for. Required.
3966 #[prost(string, tag="1")]
3967 pub group_id: ::prost::alloc::string::String,
3968}
3969/// Response containing behavioral archetypes for a group.
3970#[derive(Clone, PartialEq, ::prost::Message)]
3971pub struct GetGroupArchetypesResponse {
3972 /// Behavioral archetypes for the group (empty if insufficient data).
3973 #[prost(message, repeated, tag="1")]
3974 pub archetypes: ::prost::alloc::vec::Vec<Archetype>,
3975 /// Number of anonymous feature vectors used for clustering.
3976 #[prost(int32, tag="2")]
3977 pub data_point_count: i32,
3978 /// Why `archetypes` looks the way it does. Lets the UI render a
3979 /// distinct empty-state affordance for "never trained" vs
3980 /// "below threshold" vs "no clusters" vs "ready". See PipelineState.
3981 #[prost(enumeration="PipelineState", tag="3")]
3982 pub pipeline_state: i32,
3983 /// Confidence in the returned archetypes, derived from available data
3984 /// volume. Always CONFIDENCE_LEVEL_LOW when provisional archetypes
3985 /// are returned — clients use this plus `Archetype.source` to render
3986 /// the low-confidence disclaimer.
3987 #[prost(enumeration="ConfidenceLevel", tag="4")]
3988 pub confidence_level: i32,
3989}
3990/// Request to predict cohort-level ACK rate for a campaign configuration.
3991#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
3992pub struct PredictCampaignAckRequest {
3993 /// ID of the target audience group. Required.
3994 #[prost(string, tag="1")]
3995 pub group_id: ::prost::alloc::string::String,
3996 /// Template type (optional, for prediction refinement).
3997 #[prost(string, tag="2")]
3998 pub template_type: ::prost::alloc::string::String,
3999 /// Number of workflow steps (optional, for prediction refinement).
4000 #[prost(int32, tag="3")]
4001 pub workflow_step_count: i32,
4002}
4003/// Response containing a cohort-level ACK prediction.
4004#[derive(Clone, Copy, PartialEq, ::prost::Message)]
4005pub struct PredictCampaignAckResponse {
4006 /// Cohort-level prediction.
4007 #[prost(message, optional, tag="1")]
4008 pub prediction: ::core::option::Option<CohortPrediction>,
4009}
4010/// Request for campaign configuration advisory.
4011#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4012pub struct GetCampaignAdvisoryRequest {
4013 /// ID of the target audience group. Required.
4014 #[prost(string, tag="1")]
4015 pub group_id: ::prost::alloc::string::String,
4016 /// Template ID (optional, for advisory context).
4017 #[prost(string, tag="2")]
4018 pub template_id: ::prost::alloc::string::String,
4019 /// Template version (optional).
4020 #[prost(int32, tag="3")]
4021 pub template_version: i32,
4022 /// Number of workflow steps (optional).
4023 #[prost(int32, tag="4")]
4024 pub workflow_step_count: i32,
4025}
4026/// Response containing campaign advisory information.
4027#[derive(Clone, PartialEq, ::prost::Message)]
4028pub struct GetCampaignAdvisoryResponse {
4029 /// Campaign advisory with prediction, suggested escalation, and archetypes.
4030 #[prost(message, optional, tag="1")]
4031 pub advisory: ::core::option::Option<CampaignAdvisory>,
4032}
4033/// Request to generate an AI narrative for a group's insights.
4034#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4035pub struct GetInsightNarrativeRequest {
4036 /// ID of the group to generate a narrative for. Required.
4037 #[prost(string, tag="1")]
4038 pub group_id: ::prost::alloc::string::String,
4039 /// Name of the prompt template to use (e.g., "campaign-advisory", "archetype-explanation").
4040 #[prost(string, tag="2")]
4041 pub prompt_name: ::prost::alloc::string::String,
4042}
4043/// Response containing an AI-generated narrative.
4044#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4045pub struct GetInsightNarrativeResponse {
4046 /// AI-generated narrative text (Markdown formatted).
4047 #[prost(string, tag="1")]
4048 pub narrative: ::prost::alloc::string::String,
4049 /// Timestamp when the narrative was generated.
4050 #[prost(message, optional, tag="2")]
4051 pub generated_at: ::core::option::Option<::prost_types::Timestamp>,
4052 /// Model identifier used for generation.
4053 #[prost(string, tag="3")]
4054 pub model_id: ::prost::alloc::string::String,
4055}
4056/// Request to manually trigger the ML training pipeline.
4057/// Empty — organization is extracted from the JWT.
4058#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4059pub struct TriggerMlPipelineRequest {
4060}
4061/// Response after triggering the ML pipeline.
4062#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4063pub struct TriggerMlPipelineResponse {
4064 /// Remaining manual retrains allowed this month.
4065 #[prost(int32, tag="1")]
4066 pub remaining_this_month: i32,
4067 /// Timestamp of the last successful training (null if never trained).
4068 #[prost(message, optional, tag="2")]
4069 pub last_trained_at: ::core::option::Option<::prost_types::Timestamp>,
4070}
4071/// Request to manually retrigger archetype clustering for a single group
4072/// without rerunning the full SageMaker training pipeline. Reuses the
4073/// already-deployed clustering model.
4074#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4075pub struct TriggerArchetypeClusteringRequest {
4076 /// Group to recluster. Org is extracted from the JWT.
4077 #[prost(string, tag="1")]
4078 pub group_id: ::prost::alloc::string::String,
4079}
4080/// Response after triggering archetype clustering for one group.
4081#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4082pub struct TriggerArchetypeClusteringResponse {
4083 /// Temporal workflow id — useful for client-side dedupe + operator
4084 /// debugging via the Temporal UI.
4085 #[prost(string, tag="1")]
4086 pub workflow_id: ::prost::alloc::string::String,
4087 /// Remaining manual retrains allowed this month. Shares the same
4088 /// monthly counter as TriggerMLPipeline (ml_manual_limit_monthly).
4089 #[prost(int32, tag="2")]
4090 pub remaining_this_month: i32,
4091 /// Timestamp of the last successful archetype clustering for this
4092 /// (org, group), null if never clustered.
4093 #[prost(message, optional, tag="3")]
4094 pub last_clustered_at: ::core::option::Option<::prost_types::Timestamp>,
4095}
4096/// Request to draft a campaign body for a given archetype using Bedrock.
4097/// Used by the Compass "Target this archetype in a new campaign" CTA to
4098/// pre-fill the campaign creation wizard's body field.
4099#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4100pub struct GenerateCampaignBodyDraftRequest {
4101 /// UUID of the source group whose archetype set the label belongs to.
4102 #[prost(string, tag="1")]
4103 pub group_id: ::prost::alloc::string::String,
4104 /// Stable archetype label, e.g. "Swift Acknowledger".
4105 #[prost(string, tag="2")]
4106 pub archetype_label: ::prost::alloc::string::String,
4107 /// Lane-recommended action copy passed through from the admin (e.g.
4108 /// "Simplify the call-to-action"). Used as a tone hint for the prompt.
4109 #[prost(string, tag="3")]
4110 pub lane_action: ::prost::alloc::string::String,
4111}
4112/// Response containing the generated draft body in Markdown.
4113#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4114pub struct GenerateCampaignBodyDraftResponse {
4115 /// Draft Markdown body, 3-5 sentences. Authored as if written for the
4116 /// recipient — does not mention the archetype name.
4117 #[prost(string, tag="1")]
4118 pub body_markdown: ::prost::alloc::string::String,
4119}
4120/// Share of an organization's campaigns exercising one lever.
4121#[derive(Clone, Copy, PartialEq, ::prost::Message)]
4122pub struct LeverShare {
4123 #[prost(enumeration="Lever", tag="1")]
4124 pub lever: i32,
4125 #[prost(int32, tag="2")]
4126 pub count: i32,
4127 /// Fraction of classified campaigns, 0..1.
4128 #[prost(float, tag="3")]
4129 pub share: f32,
4130 /// Where the majority of this lever's classifications came from.
4131 /// Consumers use this together with `avg_confidence` to present
4132 /// rule-derived mixes as estimates rather than model-grade
4133 /// classifications.
4134 #[prost(enumeration="LeverSource", tag="4")]
4135 pub dominant_source: i32,
4136 /// Mean classifier confidence across the campaigns counted here, 0..1.
4137 #[prost(float, tag="5")]
4138 pub avg_confidence: f32,
4139}
4140/// How much messaging lands on a single person over the observed window.
4141#[derive(Clone, Copy, PartialEq, ::prost::Message)]
4142pub struct RecipientLoad {
4143 #[prost(float, tag="1")]
4144 pub median_per_week: f32,
4145 #[prost(float, tag="2")]
4146 pub p90_per_week: f32,
4147 #[prost(int32, tag="3")]
4148 pub users_reached: i32,
4149 #[prost(int32, tag="4")]
4150 pub window_days: i32,
4151 /// Median number of distinct senders reaching one recipient within
4152 /// the same window.
4153 #[prost(float, tag="5")]
4154 pub median_distinct_senders: f32,
4155 /// 90th-percentile number of distinct senders reaching one recipient
4156 /// within the same window.
4157 #[prost(float, tag="6")]
4158 pub p90_distinct_senders: f32,
4159 /// Median number of distinct channels one recipient is reached on
4160 /// within the same window.
4161 #[prost(float, tag="7")]
4162 pub median_distinct_channels: f32,
4163 /// 90th-percentile number of distinct channels one recipient is
4164 /// reached on within the same window.
4165 #[prost(float, tag="8")]
4166 pub p90_distinct_channels: f32,
4167}
4168#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4169pub struct GetOrgCommunicationProfileRequest {
4170}
4171#[derive(Clone, PartialEq, ::prost::Message)]
4172pub struct GetOrgCommunicationProfileResponse {
4173 #[prost(message, repeated, tag="1")]
4174 pub lever_mix: ::prost::alloc::vec::Vec<LeverShare>,
4175 #[prost(message, optional, tag="2")]
4176 pub load: ::core::option::Option<RecipientLoad>,
4177 #[prost(int32, tag="3")]
4178 pub campaigns_analyzed: i32,
4179 /// Fraction of active objectives that have at least one indicator
4180 /// whose evidence comes from outside the product, 0..1.
4181 ///
4182 /// It says how much the rest of the board is worth: an objective
4183 /// observed only through what people answered inside the app has
4184 /// evidence that they said they did it, not evidence that the work
4185 /// changed.
4186 ///
4187 /// Absent when `active_objectives` is zero, because a fraction with no
4188 /// denominator has no value and a present 0.0 would be
4189 /// indistinguishable from genuine coverage of none — opposite facts
4190 /// with opposite consequences. The two counts below travel with it as
4191 /// the second half of the same guarantee.
4192 #[prost(float, optional, tag="4")]
4193 pub evidence_coverage: ::core::option::Option<f32>,
4194 /// Numerator of `evidence_coverage`: active objectives with at least
4195 /// one indicator sourced outside the product.
4196 #[prost(int32, tag="5")]
4197 pub objectives_with_external_evidence: i32,
4198 /// Denominator of `evidence_coverage`: active objectives. Zero means
4199 /// the organization has declared none, which is a supported way to use
4200 /// the product and not an incomplete setup.
4201 #[prost(int32, tag="6")]
4202 pub active_objectives: i32,
4203 /// Median number of days since the organization's indicators were last
4204 /// revised, measured from each indicator's last update.
4205 ///
4206 /// Indicators are rarely revisited when the strategy they serve moves
4207 /// on, and this is the plainest measurable form of that: an ageing
4208 /// median means the board is describing an older intent than the
4209 /// objectives do.
4210 ///
4211 /// Absent when the organization has no indicators. An age of zero
4212 /// would claim they were all just reviewed.
4213 #[prost(int64, optional, tag="7")]
4214 pub median_indicator_review_age_days: ::core::option::Option<i64>,
4215}
4216/// One observation in a diagnosis.
4217///
4218/// Every finding carries the records it was derived from. That is not
4219/// decoration: a statement about an organization that cannot be traced
4220/// back to the campaigns, objectives and indicators that produced it is
4221/// indistinguishable from an opinion, and the reader has no way to
4222/// disagree with it on the facts. At least one of the three reference
4223/// lists is always non-empty.
4224#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4225pub struct DiagnosisFinding {
4226 /// Unique identifier for the finding, stable within the diagnosis.
4227 /// Lets a surface show a finding once at the level where it can be
4228 /// acted on instead of repeating it as a loose warning elsewhere.
4229 #[prost(string, tag="1")]
4230 pub id: ::prost::alloc::string::String,
4231 /// Which pattern produced it.
4232 #[prost(enumeration="DiagnosisFindingKind", tag="2")]
4233 pub kind: i32,
4234 /// What was observed, in the organization's own terms. Plain language
4235 /// and free of the vocabulary of the framework the pattern comes from.
4236 #[prost(string, tag="3")]
4237 pub detail: ::prost::alloc::string::String,
4238 /// Campaigns the finding was derived from.
4239 #[prost(string, repeated, tag="4")]
4240 pub campaign_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
4241 /// Objectives the finding was derived from.
4242 #[prost(string, repeated, tag="5")]
4243 pub objective_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
4244 /// Indicators the finding was derived from.
4245 #[prost(string, repeated, tag="6")]
4246 pub indicator_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
4247 /// True when a model wrote `detail`. A model only ever phrases a
4248 /// finding that was already established from the records above; it
4249 /// never decides that there is one. Consumers use this the way they
4250 /// use lever provenance — to present a phrasing as a phrasing.
4251 #[prost(bool, tag="7")]
4252 pub model_assisted: bool,
4253}
4254/// The organization-level metrics as they stood when a diagnosis was
4255/// produced, stored with it.
4256///
4257/// Kept rather than recomputed because two of the four cannot be
4258/// recovered afterwards. Evidence coverage and the indicator review age
4259/// are read off the objectives and indicators as they are configured at
4260/// that moment, and configuration has no history: an objective archived
4261/// or an indicator revised next month silently rewrites what last
4262/// month's answer would have been. A diagnosis stored without its
4263/// snapshot therefore loses the comparison permanently, and the
4264/// comparison is most of why the diagnosis is stored at all.
4265///
4266/// Fields carry presence on the same terms as the profile response they
4267/// mirror: absent means there was nothing to measure, never zero.
4268#[derive(Clone, PartialEq, ::prost::Message)]
4269pub struct OrgMetricsSnapshot {
4270 /// Distribution of the classified history across control mechanisms.
4271 #[prost(message, repeated, tag="1")]
4272 pub lever_mix: ::prost::alloc::vec::Vec<LeverShare>,
4273 /// How much messaging landed on one person over the observed window.
4274 #[prost(message, optional, tag="2")]
4275 pub load: ::core::option::Option<RecipientLoad>,
4276 /// Fraction of active objectives with at least one indicator sourced
4277 /// outside the product, 0..1. Absent when there were no active
4278 /// objectives.
4279 #[prost(float, optional, tag="3")]
4280 pub evidence_coverage: ::core::option::Option<f32>,
4281 /// Numerator of `evidence_coverage` at generation time.
4282 #[prost(int32, tag="4")]
4283 pub objectives_with_external_evidence: i32,
4284 /// Denominator of `evidence_coverage` at generation time.
4285 #[prost(int32, tag="5")]
4286 pub active_objectives: i32,
4287 /// Median days since the organization's indicators were last revised.
4288 /// Absent when there were no indicators.
4289 #[prost(int64, optional, tag="6")]
4290 pub median_indicator_review_age_days: ::core::option::Option<i64>,
4291}
4292/// A dated, stored reading of the organization's own measurement system:
4293/// what it has declared it wants, how it observes it, and what it has
4294/// actually been communicating.
4295///
4296/// Stored rather than computed on request because the useful statements
4297/// are comparisons — that the mix of messages moved over a quarter, that
4298/// three objectives still have no outcome evidence months later — and a
4299/// stateless query cannot make them. It is also the only shape in which a
4300/// recurring review has something to review.
4301#[derive(Clone, PartialEq, ::prost::Message)]
4302pub struct OrgDiagnosis {
4303 /// Unique identifier for this run.
4304 #[prost(string, tag="1")]
4305 pub id: ::prost::alloc::string::String,
4306 /// When the run was produced.
4307 #[prost(message, optional, tag="2")]
4308 pub generated_at: ::core::option::Option<::prost_types::Timestamp>,
4309 /// What the run found. Empty when the configuration and the history
4310 /// gave nothing to say, which is a real result: a system that always
4311 /// has an opinion stops being read.
4312 #[prost(message, repeated, tag="3")]
4313 pub findings: ::prost::alloc::vec::Vec<DiagnosisFinding>,
4314 /// The previous run, when there is one. What changed between the two
4315 /// is the part of a diagnosis that no single run can carry.
4316 #[prost(string, tag="4")]
4317 pub previous_diagnosis_id: ::prost::alloc::string::String,
4318 /// Objectives read by the run.
4319 #[prost(int32, tag="5")]
4320 pub objectives_analyzed: i32,
4321 /// Campaigns read by the run.
4322 #[prost(int32, tag="6")]
4323 pub campaigns_analyzed: i32,
4324 /// The metrics as they stood at generation time. What moved between
4325 /// two runs is the part of a diagnosis that no single run can state,
4326 /// and this is what makes it recoverable later.
4327 #[prost(message, optional, tag="7")]
4328 pub metrics: ::core::option::Option<OrgMetricsSnapshot>,
4329}
4330/// Request for a stored organization diagnosis.
4331#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4332pub struct GetOrgDiagnosisRequest {
4333 /// Retrieve a specific run. Empty returns the most recent one.
4334 /// An id that does not exist returns NOT_FOUND.
4335 #[prost(string, tag="1")]
4336 pub diagnosis_id: ::prost::alloc::string::String,
4337}
4338/// Response containing an organization diagnosis.
4339#[derive(Clone, PartialEq, ::prost::Message)]
4340pub struct GetOrgDiagnosisResponse {
4341 /// The diagnosis. Absent when no run has ever been produced for the
4342 /// organization — a run needs declared objectives to have anything to
4343 /// read, and does not happen without them. Absence is presented as
4344 /// absence, never as a diagnosis with no findings, which would say
4345 /// something quite different.
4346 #[prost(message, optional, tag="1")]
4347 pub diagnosis: ::core::option::Option<OrgDiagnosis>,
4348}
4349/// Request to list an organization's diagnoses with pagination.
4350#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4351pub struct ListOrgDiagnosesRequest {
4352 /// Pagination parameters.
4353 #[prost(message, optional, tag="1")]
4354 pub pagination: ::core::option::Option<Pagination>,
4355}
4356/// Response containing a page of diagnoses.
4357#[derive(Clone, PartialEq, ::prost::Message)]
4358pub struct ListOrgDiagnosesResponse {
4359 /// Diagnoses in this page, newest first. Each carries its own metrics
4360 /// snapshot, so a page is enough to plot how the organization's
4361 /// measurement system moved without walking the chain of previous
4362 /// runs one fetch at a time.
4363 #[prost(message, repeated, tag="1")]
4364 pub diagnoses: ::prost::alloc::vec::Vec<OrgDiagnosis>,
4365 /// Pagination metadata for fetching subsequent pages.
4366 #[prost(message, optional, tag="2")]
4367 pub pagination_meta: ::core::option::Option<PaginationMeta>,
4368}
4369/// Request to run a diagnosis now.
4370/// Empty — organization is extracted from the JWT.
4371#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4372pub struct TriggerOrgDiagnosisRequest {
4373}
4374/// Response after triggering a diagnosis run.
4375#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4376pub struct TriggerOrgDiagnosisResponse {
4377 /// Remaining manual runs allowed this month.
4378 #[prost(int32, tag="1")]
4379 pub remaining_this_month: i32,
4380 /// Timestamp of the last diagnosis produced, null if never run.
4381 #[prost(message, optional, tag="2")]
4382 pub last_generated_at: ::core::option::Option<::prost_types::Timestamp>,
4383}
4384// ─── Enums ──────────────────────────────────────────────────────────────────
4385
4386/// Confidence level for cohort-level predictions, based on available data volume.
4387#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4388#[repr(i32)]
4389pub enum ConfidenceLevel {
4390 Unspecified = 0,
4391 /// Fewer than 50 campaigns — predictions based on heuristics/industry benchmarks.
4392 Low = 1,
4393 /// 50-200 campaigns — basic clustering available, wide confidence intervals.
4394 Medium = 2,
4395 /// 200+ campaigns — full ML pipeline, narrow confidence intervals.
4396 High = 3,
4397}
4398impl ConfidenceLevel {
4399 /// String value of the enum field names used in the ProtoBuf definition.
4400 ///
4401 /// The values are not transformed in any way and thus are considered stable
4402 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4403 pub fn as_str_name(&self) -> &'static str {
4404 match self {
4405 Self::Unspecified => "CONFIDENCE_LEVEL_UNSPECIFIED",
4406 Self::Low => "CONFIDENCE_LEVEL_LOW",
4407 Self::Medium => "CONFIDENCE_LEVEL_MEDIUM",
4408 Self::High => "CONFIDENCE_LEVEL_HIGH",
4409 }
4410 }
4411 /// Creates an enum from field names used in the ProtoBuf definition.
4412 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4413 match value {
4414 "CONFIDENCE_LEVEL_UNSPECIFIED" => Some(Self::Unspecified),
4415 "CONFIDENCE_LEVEL_LOW" => Some(Self::Low),
4416 "CONFIDENCE_LEVEL_MEDIUM" => Some(Self::Medium),
4417 "CONFIDENCE_LEVEL_HIGH" => Some(Self::High),
4418 _ => None,
4419 }
4420 }
4421}
4422/// Pipeline state for a group's archetypes. Lets the admin UI render
4423/// distinct empty-state affordances ("run clustering" vs "need N more
4424/// sessions" vs "pipeline ran but audience was too homogeneous") instead
4425/// of treating every empty archetype list the same. Populated by
4426/// InsightsService.GetGroupArchetypes.
4427#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4428#[repr(i32)]
4429pub enum PipelineState {
4430 Unspecified = 0,
4431 /// The ML pipeline has never fired for this org. Archetypes are
4432 /// empty because nothing ran, not because of data shape.
4433 NeverRun = 1,
4434 /// The pipeline ran but the group had fewer than the k-anonymization
4435 /// minimum feature vectors (50), so clustering was skipped. UI
4436 /// renders "keep running campaigns" affordance.
4437 BelowThreshold = 2,
4438 /// The pipeline ran with enough vectors but the clustering provider
4439 /// returned zero clusters — typically means the audience is too
4440 /// homogeneous to separate into distinct archetypes.
4441 NoClusters = 3,
4442 /// Archetypes are populated and ready to render.
4443 Ready = 4,
4444}
4445impl PipelineState {
4446 /// String value of the enum field names used in the ProtoBuf definition.
4447 ///
4448 /// The values are not transformed in any way and thus are considered stable
4449 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4450 pub fn as_str_name(&self) -> &'static str {
4451 match self {
4452 Self::Unspecified => "PIPELINE_STATE_UNSPECIFIED",
4453 Self::NeverRun => "PIPELINE_STATE_NEVER_RUN",
4454 Self::BelowThreshold => "PIPELINE_STATE_BELOW_THRESHOLD",
4455 Self::NoClusters => "PIPELINE_STATE_NO_CLUSTERS",
4456 Self::Ready => "PIPELINE_STATE_READY",
4457 }
4458 }
4459 /// Creates an enum from field names used in the ProtoBuf definition.
4460 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4461 match value {
4462 "PIPELINE_STATE_UNSPECIFIED" => Some(Self::Unspecified),
4463 "PIPELINE_STATE_NEVER_RUN" => Some(Self::NeverRun),
4464 "PIPELINE_STATE_BELOW_THRESHOLD" => Some(Self::BelowThreshold),
4465 "PIPELINE_STATE_NO_CLUSTERS" => Some(Self::NoClusters),
4466 "PIPELINE_STATE_READY" => Some(Self::Ready),
4467 _ => None,
4468 }
4469 }
4470}
4471/// Where an archetype came from. Lets clients distinguish trained ML
4472/// clustering output from low-confidence provisional output generated
4473/// for sandboxes and opted-in organizations before enough engagement
4474/// data exists. Clients MUST render a low-confidence disclaimer for
4475/// PROVISIONAL archetypes.
4476#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4477#[repr(i32)]
4478pub enum ArchetypeSource {
4479 Unspecified = 0,
4480 /// Produced by the trained ML clustering pipeline (k-anonymized,
4481 /// DP-noised behavioral feature vectors).
4482 Ml = 1,
4483 /// Rule-based provisional output derived from coarse delivery/read/
4484 /// ack activity (or a stable starter distribution for sandboxes with
4485 /// no activity). Low confidence, never written to the ML artifact
4486 /// path, and always superseded by ML output once available.
4487 Provisional = 2,
4488}
4489impl ArchetypeSource {
4490 /// String value of the enum field names used in the ProtoBuf definition.
4491 ///
4492 /// The values are not transformed in any way and thus are considered stable
4493 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4494 pub fn as_str_name(&self) -> &'static str {
4495 match self {
4496 Self::Unspecified => "ARCHETYPE_SOURCE_UNSPECIFIED",
4497 Self::Ml => "ARCHETYPE_SOURCE_ML",
4498 Self::Provisional => "ARCHETYPE_SOURCE_PROVISIONAL",
4499 }
4500 }
4501 /// Creates an enum from field names used in the ProtoBuf definition.
4502 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4503 match value {
4504 "ARCHETYPE_SOURCE_UNSPECIFIED" => Some(Self::Unspecified),
4505 "ARCHETYPE_SOURCE_ML" => Some(Self::Ml),
4506 "ARCHETYPE_SOURCE_PROVISIONAL" => Some(Self::Provisional),
4507 _ => None,
4508 }
4509 }
4510}
4511/// Which control mechanism a message exercises. Names are technical; clients
4512/// render plain-language labels from their own catalog.
4513#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4514#[repr(i32)]
4515pub enum Lever {
4516 Unspecified = 0,
4517 Boundaries = 1,
4518 Diagnostic = 2,
4519 Beliefs = 3,
4520 Interactive = 4,
4521}
4522impl Lever {
4523 /// String value of the enum field names used in the ProtoBuf definition.
4524 ///
4525 /// The values are not transformed in any way and thus are considered stable
4526 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4527 pub fn as_str_name(&self) -> &'static str {
4528 match self {
4529 Self::Unspecified => "LEVER_UNSPECIFIED",
4530 Self::Boundaries => "LEVER_BOUNDARIES",
4531 Self::Diagnostic => "LEVER_DIAGNOSTIC",
4532 Self::Beliefs => "LEVER_BELIEFS",
4533 Self::Interactive => "LEVER_INTERACTIVE",
4534 }
4535 }
4536 /// Creates an enum from field names used in the ProtoBuf definition.
4537 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4538 match value {
4539 "LEVER_UNSPECIFIED" => Some(Self::Unspecified),
4540 "LEVER_BOUNDARIES" => Some(Self::Boundaries),
4541 "LEVER_DIAGNOSTIC" => Some(Self::Diagnostic),
4542 "LEVER_BELIEFS" => Some(Self::Beliefs),
4543 "LEVER_INTERACTIVE" => Some(Self::Interactive),
4544 _ => None,
4545 }
4546 }
4547}
4548/// How a lever classification was produced.
4549#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4550#[repr(i32)]
4551pub enum LeverSource {
4552 Unspecified = 0,
4553 /// Produced by a trained classification model.
4554 Model = 1,
4555 /// Produced by deterministic rules over campaign metadata.
4556 Rules = 2,
4557}
4558impl LeverSource {
4559 /// String value of the enum field names used in the ProtoBuf definition.
4560 ///
4561 /// The values are not transformed in any way and thus are considered stable
4562 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4563 pub fn as_str_name(&self) -> &'static str {
4564 match self {
4565 Self::Unspecified => "LEVER_SOURCE_UNSPECIFIED",
4566 Self::Model => "LEVER_SOURCE_MODEL",
4567 Self::Rules => "LEVER_SOURCE_RULES",
4568 }
4569 }
4570 /// Creates an enum from field names used in the ProtoBuf definition.
4571 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4572 match value {
4573 "LEVER_SOURCE_UNSPECIFIED" => Some(Self::Unspecified),
4574 "LEVER_SOURCE_MODEL" => Some(Self::Model),
4575 "LEVER_SOURCE_RULES" => Some(Self::Rules),
4576 _ => None,
4577 }
4578 }
4579}
4580/// Which pattern a finding came from. The scope a pattern is entitled to
4581/// speak at is fixed per kind and not a separate field: mutual exclusivity
4582/// and lever mix are properties of the whole declared set, board size and
4583/// drift are properties of one objective, and encouraged behaviour is a
4584/// property of one indicator. Evaluating any of them at another scope is a
4585/// category error rather than a partial view.
4586#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4587#[repr(i32)]
4588pub enum DiagnosisFindingKind {
4589 Unspecified = 0,
4590 /// An indicator whose evidence source structurally fails one of the
4591 /// qualities a measure needs, and the behaviour that tends to follow.
4592 PerverseConductRisk = 1,
4593 /// The organization's messages concentrate in some control mechanisms
4594 /// and leave others unused, with the consequences the missing ones
4595 /// would have covered.
4596 LeverImbalance = 2,
4597 /// The declared objectives overlap each other or leave gaps, so the
4598 /// set does not partition what the organization is trying to hold
4599 /// true.
4600 NonExclusiveSet = 3,
4601 /// An objective carries more indicators than anyone reads, or several
4602 /// that measure the same thing by different routes.
4603 InflatedBoard = 4,
4604 /// An objective's wording changed and none of its indicators was
4605 /// revisited afterwards.
4606 ObjectiveIndicatorDrift = 5,
4607}
4608impl DiagnosisFindingKind {
4609 /// String value of the enum field names used in the ProtoBuf definition.
4610 ///
4611 /// The values are not transformed in any way and thus are considered stable
4612 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4613 pub fn as_str_name(&self) -> &'static str {
4614 match self {
4615 Self::Unspecified => "DIAGNOSIS_FINDING_KIND_UNSPECIFIED",
4616 Self::PerverseConductRisk => "DIAGNOSIS_FINDING_KIND_PERVERSE_CONDUCT_RISK",
4617 Self::LeverImbalance => "DIAGNOSIS_FINDING_KIND_LEVER_IMBALANCE",
4618 Self::NonExclusiveSet => "DIAGNOSIS_FINDING_KIND_NON_EXCLUSIVE_SET",
4619 Self::InflatedBoard => "DIAGNOSIS_FINDING_KIND_INFLATED_BOARD",
4620 Self::ObjectiveIndicatorDrift => "DIAGNOSIS_FINDING_KIND_OBJECTIVE_INDICATOR_DRIFT",
4621 }
4622 }
4623 /// Creates an enum from field names used in the ProtoBuf definition.
4624 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4625 match value {
4626 "DIAGNOSIS_FINDING_KIND_UNSPECIFIED" => Some(Self::Unspecified),
4627 "DIAGNOSIS_FINDING_KIND_PERVERSE_CONDUCT_RISK" => Some(Self::PerverseConductRisk),
4628 "DIAGNOSIS_FINDING_KIND_LEVER_IMBALANCE" => Some(Self::LeverImbalance),
4629 "DIAGNOSIS_FINDING_KIND_NON_EXCLUSIVE_SET" => Some(Self::NonExclusiveSet),
4630 "DIAGNOSIS_FINDING_KIND_INFLATED_BOARD" => Some(Self::InflatedBoard),
4631 "DIAGNOSIS_FINDING_KIND_OBJECTIVE_INDICATOR_DRIFT" => Some(Self::ObjectiveIndicatorDrift),
4632 _ => None,
4633 }
4634 }
4635}
4636// ─── Messages ───────────────────────────────────────────────────────────────
4637
4638/// A single reachability registry row, returned by `GetReachability` and
4639/// `ListReachabilityForUser`. The plaintext identifier and envelope ciphertext
4640/// are NEVER returned over the wire — only metadata. The dispatch worker reads
4641/// the plaintext directly from the database and decrypts via KMS.
4642#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4643pub struct Reachability {
4644 /// Server-assigned row identifier (UUID).
4645 #[prost(string, tag="1")]
4646 pub id: ::prost::alloc::string::String,
4647 /// Organization that owns this reachability entry.
4648 #[prost(string, tag="2")]
4649 pub org_id: ::prost::alloc::string::String,
4650 /// User this reachability entry is for.
4651 #[prost(string, tag="3")]
4652 pub user_id: ::prost::alloc::string::String,
4653 /// Channel for which this entry stores a contact identifier.
4654 #[prost(enumeration="ChannelName", tag="4")]
4655 pub channel: i32,
4656 /// When the row was first written.
4657 #[prost(message, optional, tag="5")]
4658 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
4659 /// When the row was last upserted.
4660 #[prost(message, optional, tag="6")]
4661 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
4662 /// Optional AWS region identifier (e.g. "eu-west-1") this user's data must
4663 /// remain in for GDPR/residency reasons. Unset means "no constraint."
4664 /// Enforcement happens at dispatch time, not write time.
4665 #[prost(string, optional, tag="7")]
4666 pub region_constraint: ::core::option::Option<::prost::alloc::string::String>,
4667}
4668/// Per-(org, channel) region allowlist used by the dispatch worker to enforce
4669/// data-residency policy. An empty `allowed_regions` list means "no policy
4670/// configured" — NOT "no regions allowed."
4671#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4672pub struct RegionPolicy {
4673 #[prost(string, tag="1")]
4674 pub org_id: ::prost::alloc::string::String,
4675 #[prost(enumeration="ChannelName", tag="2")]
4676 pub channel: i32,
4677 /// AWS region identifiers (e.g. "eu-west-1", "us-east-1"). Empty list ==
4678 /// "no policy configured" — the dispatch worker SHALL NOT block on empty.
4679 #[prost(string, repeated, tag="3")]
4680 pub allowed_regions: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
4681 #[prost(message, optional, tag="4")]
4682 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
4683}
4684// ─── Enums ──────────────────────────────────────────────────────────────────
4685
4686/// Terminal status of a single dispatch attempt as returned by the worker-mode
4687/// `DispatchToChannel` RPC. Distinct from the richer `ChannelEventStatus` in
4688/// `channel_events.proto`, which models the audit-trail row for every state
4689/// transition (SENT → DELIVERED → OPENED → …). DispatchStatus is the immediate
4690/// outcome of one worker call.
4691#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
4692#[repr(i32)]
4693pub enum DispatchStatus {
4694 /// Default value; should not be used explicitly.
4695 Unspecified = 0,
4696 /// The adapter accepted the message for delivery (provider returned success).
4697 Sent = 1,
4698 /// The adapter returned a terminal error (e.g. recipient blocked, domain not
4699 /// verified). Retries SHALL NOT be attempted; consult `failure_reason`.
4700 Failed = 2,
4701 /// An existing `(dispatch_id, SENT)` row was found by the idempotency guard
4702 /// before the adapter was called; the prior receipt was returned without a
4703 /// second provider call.
4704 Deduped = 3,
4705}
4706impl DispatchStatus {
4707 /// String value of the enum field names used in the ProtoBuf definition.
4708 ///
4709 /// The values are not transformed in any way and thus are considered stable
4710 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
4711 pub fn as_str_name(&self) -> &'static str {
4712 match self {
4713 Self::Unspecified => "DISPATCH_STATUS_UNSPECIFIED",
4714 Self::Sent => "DISPATCH_STATUS_SENT",
4715 Self::Failed => "DISPATCH_STATUS_FAILED",
4716 Self::Deduped => "DISPATCH_STATUS_DEDUPED",
4717 }
4718 }
4719 /// Creates an enum from field names used in the ProtoBuf definition.
4720 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
4721 match value {
4722 "DISPATCH_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
4723 "DISPATCH_STATUS_SENT" => Some(Self::Sent),
4724 "DISPATCH_STATUS_FAILED" => Some(Self::Failed),
4725 "DISPATCH_STATUS_DEDUPED" => Some(Self::Deduped),
4726 _ => None,
4727 }
4728 }
4729}
4730// ─── DispatchToChannel ──────────────────────────────────────────────────────
4731
4732/// Worker-mode entry point invoked by the Temporal worker for one recipient.
4733/// Idempotent on `dispatch_id`: if a `(dispatch_id, SENT)` row already exists
4734/// in `channel_dispatches`, the worker SHALL return DISPATCH_STATUS_DEDUPED
4735/// without re-invoking the channel adapter.
4736#[derive(Clone, PartialEq, ::prost::Message)]
4737pub struct DispatchToChannelRequest {
4738 /// Idempotency key. Must be stable across retries from pidgr-api side.
4739 #[prost(string, tag="1")]
4740 pub dispatch_id: ::prost::alloc::string::String,
4741 #[prost(string, tag="2")]
4742 pub org_id: ::prost::alloc::string::String,
4743 #[prost(string, tag="3")]
4744 pub user_id: ::prost::alloc::string::String,
4745 /// Which channel adapter to invoke (EMAIL is the Wave 1 implementation).
4746 #[prost(enumeration="ChannelName", tag="4")]
4747 pub channel: i32,
4748 /// Template to render before dispatch.
4749 #[prost(string, tag="5")]
4750 pub template_id: ::prost::alloc::string::String,
4751 /// Per-recipient template variables.
4752 #[prost(map="string, string", tag="6")]
4753 pub template_vars: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
4754 /// BCP-47 locale used to select the template translation.
4755 #[prost(string, tag="7")]
4756 pub locale: ::prost::alloc::string::String,
4757 /// Optional AWS region the worker MUST dispatch from (typically copied from
4758 /// the recipient's reachability row). Unset means "no constraint."
4759 #[prost(string, optional, tag="8")]
4760 pub region_constraint: ::core::option::Option<::prost::alloc::string::String>,
4761}
4762#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4763pub struct DispatchToChannelResponse {
4764 /// Echoes back the request's `dispatch_id`.
4765 #[prost(string, tag="1")]
4766 pub dispatch_id: ::prost::alloc::string::String,
4767 /// Terminal outcome of this call.
4768 #[prost(enumeration="DispatchStatus", tag="2")]
4769 pub status: i32,
4770 /// Human-readable failure reason; set only when `status` is
4771 /// DISPATCH_STATUS_FAILED.
4772 #[prost(string, optional, tag="3")]
4773 pub failure_reason: ::core::option::Option<::prost::alloc::string::String>,
4774}
4775// ─── UpsertReachability ─────────────────────────────────────────────────────
4776
4777/// Records a recipient identifier for a (user, channel) tuple. The plaintext
4778/// identifier is column-level KMS-encrypted on insert and never logged or
4779/// returned. The server computes the org-scoped HMAC lookup hash so opt-out
4780/// webhooks can find the row without decrypt.
4781#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4782pub struct UpsertReachabilityRequest {
4783 #[prost(string, tag="1")]
4784 pub org_id: ::prost::alloc::string::String,
4785 #[prost(string, tag="2")]
4786 pub user_id: ::prost::alloc::string::String,
4787 #[prost(enumeration="ChannelName", tag="3")]
4788 pub channel: i32,
4789 /// The plaintext identifier (email address, phone number, Slack user ID,
4790 /// Telegram chat ID, etc.). Encrypted at rest server-side. Servers MUST NOT
4791 /// log this field. Clients SHOULD treat this message as sensitive.
4792 #[prost(string, tag="4")]
4793 pub identifier_plaintext: ::prost::alloc::string::String,
4794 /// Optional AWS region this user's data must remain in (e.g. "eu-west-1").
4795 /// Recorded but NOT enforced at write time; enforcement is at dispatch.
4796 #[prost(string, optional, tag="5")]
4797 pub region_constraint: ::core::option::Option<::prost::alloc::string::String>,
4798}
4799#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4800pub struct UpsertReachabilityResponse {
4801 /// The metadata for the upserted row. Plaintext identifier and envelope
4802 /// ciphertext are intentionally absent.
4803 #[prost(message, optional, tag="1")]
4804 pub reachability: ::core::option::Option<Reachability>,
4805}
4806// ─── RemoveReachability ─────────────────────────────────────────────────────
4807
4808/// Idempotent removal. GDPR Recital 30 audit row is appended via internal-mTLS
4809/// BEFORE the registry row is deleted (see AuditService.Append). If no row
4810/// existed, `removed = false` and no audit row is emitted.
4811#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4812pub struct RemoveReachabilityRequest {
4813 #[prost(string, tag="1")]
4814 pub org_id: ::prost::alloc::string::String,
4815 #[prost(string, tag="2")]
4816 pub user_id: ::prost::alloc::string::String,
4817 #[prost(enumeration="ChannelName", tag="3")]
4818 pub channel: i32,
4819}
4820#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
4821pub struct RemoveReachabilityResponse {
4822 /// True if a row was deleted. False if no row existed for the tuple
4823 /// (idempotent success).
4824 #[prost(bool, tag="1")]
4825 pub removed: bool,
4826}
4827// ─── GetReachability ────────────────────────────────────────────────────────
4828
4829/// Returns the reachability metadata for a single (user, channel) tuple.
4830/// Returns NOT_FOUND if no row exists.
4831#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4832pub struct GetReachabilityRequest {
4833 #[prost(string, tag="1")]
4834 pub org_id: ::prost::alloc::string::String,
4835 #[prost(string, tag="2")]
4836 pub user_id: ::prost::alloc::string::String,
4837 #[prost(enumeration="ChannelName", tag="3")]
4838 pub channel: i32,
4839}
4840#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4841pub struct GetReachabilityResponse {
4842 /// Plaintext identifier and envelope ciphertext are intentionally absent.
4843 #[prost(message, optional, tag="1")]
4844 pub reachability: ::core::option::Option<Reachability>,
4845}
4846// ─── ListReachabilityForUser ────────────────────────────────────────────────
4847
4848/// Returns one Reachability entry per channel configured for a (org, user)
4849/// pair. Used by the admin-side per-user matrix view. Plaintext identifiers
4850/// and envelope ciphertext are intentionally absent — the admin UI only needs
4851/// to know which channels are configured.
4852#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4853pub struct ListReachabilityForUserRequest {
4854 #[prost(string, tag="1")]
4855 pub org_id: ::prost::alloc::string::String,
4856 #[prost(string, tag="2")]
4857 pub user_id: ::prost::alloc::string::String,
4858}
4859#[derive(Clone, PartialEq, ::prost::Message)]
4860pub struct ListReachabilityForUserResponse {
4861 /// One entry per channel that has a row for the (org_id, user_id) pair.
4862 #[prost(message, repeated, tag="1")]
4863 pub reachabilities: ::prost::alloc::vec::Vec<Reachability>,
4864}
4865// ─── GetRegionPolicy / SetRegionPolicy ──────────────────────────────────────
4866
4867#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4868pub struct GetRegionPolicyRequest {
4869 #[prost(string, tag="1")]
4870 pub org_id: ::prost::alloc::string::String,
4871 #[prost(enumeration="ChannelName", tag="2")]
4872 pub channel: i32,
4873}
4874#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4875pub struct GetRegionPolicyResponse {
4876 /// Always populated. Empty `allowed_regions` means "no policy configured"
4877 /// — NOT "no regions allowed."
4878 #[prost(message, optional, tag="1")]
4879 pub policy: ::core::option::Option<RegionPolicy>,
4880}
4881/// Admin-only upsert. Empty `allowed_regions` clears the policy.
4882#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4883pub struct SetRegionPolicyRequest {
4884 #[prost(string, tag="1")]
4885 pub org_id: ::prost::alloc::string::String,
4886 #[prost(enumeration="ChannelName", tag="2")]
4887 pub channel: i32,
4888 /// AWS region identifiers (e.g. "eu-west-1"). Empty list == "no policy."
4889 #[prost(string, repeated, tag="3")]
4890 pub allowed_regions: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
4891}
4892#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4893pub struct SetRegionPolicyResponse {
4894 #[prost(message, optional, tag="1")]
4895 pub policy: ::core::option::Option<RegionPolicy>,
4896}
4897// ─── GetCostCapPolicy / SetCostCapPolicy ────────────────────────────────────
4898
4899/// Get the cost-cap state for the current calendar-month period (UTC). When
4900/// no row exists for `(org_id, channel, period_yyyymm)`, the server returns
4901/// the channel default cap from server config
4902/// (`COST_CAP_DEFAULT_${CHANNEL}_MICROS`) with `used_micros = 0`.
4903#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4904pub struct GetCostCapPolicyRequest {
4905 #[prost(string, tag="1")]
4906 pub org_id: ::prost::alloc::string::String,
4907 #[prost(enumeration="ChannelName", tag="2")]
4908 pub channel: i32,
4909}
4910#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4911pub struct GetCostCapPolicyResponse {
4912 #[prost(string, tag="1")]
4913 pub org_id: ::prost::alloc::string::String,
4914 #[prost(enumeration="ChannelName", tag="2")]
4915 pub channel: i32,
4916 /// Current period's cap in micros (1/1_000_000 of a USD).
4917 #[prost(int64, tag="3")]
4918 pub cap_micros: i64,
4919 /// Current period's accumulated spend in micros.
4920 #[prost(int64, tag="4")]
4921 pub used_micros: i64,
4922 /// Calendar-month period in integer YYYYMM form (e.g. 202605 for May 2026).
4923 #[prost(int32, tag="5")]
4924 pub period_yyyymm: i32,
4925}
4926/// Admin-only upsert of the cap for the current calendar-month period. Future
4927/// periods inherit the most recent SetCostCapPolicy value until the next call.
4928#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4929pub struct SetCostCapPolicyRequest {
4930 #[prost(string, tag="1")]
4931 pub org_id: ::prost::alloc::string::String,
4932 #[prost(enumeration="ChannelName", tag="2")]
4933 pub channel: i32,
4934 #[prost(int64, tag="3")]
4935 pub cap_micros: i64,
4936}
4937#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4938pub struct SetCostCapPolicyResponse {
4939 #[prost(string, tag="1")]
4940 pub org_id: ::prost::alloc::string::String,
4941 #[prost(enumeration="ChannelName", tag="2")]
4942 pub channel: i32,
4943 #[prost(int64, tag="3")]
4944 pub cap_micros: i64,
4945 #[prost(int64, tag="4")]
4946 pub used_micros: i64,
4947 #[prost(int32, tag="5")]
4948 pub period_yyyymm: i32,
4949}
4950// ─── GetOrgWebhookConfig / SetOrgWebhookConfig ──────────────────────────────
4951
4952/// Get the org's generic-webhook channel configuration. The shared secret is
4953/// write-only and never returned — `has_secret` reports whether one is set.
4954#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4955pub struct GetOrgWebhookConfigRequest {
4956 #[prost(string, tag="1")]
4957 pub org_id: ::prost::alloc::string::String,
4958}
4959#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4960pub struct GetOrgWebhookConfigResponse {
4961 #[prost(string, tag="1")]
4962 pub org_id: ::prost::alloc::string::String,
4963 /// Destination URL Pidgr POSTs notification events to. Empty when no
4964 /// configuration exists.
4965 #[prost(string, tag="2")]
4966 pub url: ::prost::alloc::string::String,
4967 /// Whether dispatch via the WEBHOOK channel is enabled for the org.
4968 #[prost(bool, tag="3")]
4969 pub enabled: bool,
4970 /// Whether a signing secret is currently configured. The secret itself is
4971 /// never returned.
4972 #[prost(bool, tag="4")]
4973 pub has_secret: bool,
4974 #[prost(message, optional, tag="5")]
4975 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
4976 #[prost(message, optional, tag="6")]
4977 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
4978}
4979/// Admin-only upsert of the org's generic-webhook configuration. The server
4980/// validates the URL (https-only, public addresses only) before persisting,
4981/// and envelope-encrypts the secret at rest. Setting a new `secret` rotates
4982/// it; leaving `secret` unset keeps the existing one.
4983#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
4984pub struct SetOrgWebhookConfigRequest {
4985 #[prost(string, tag="1")]
4986 pub org_id: ::prost::alloc::string::String,
4987 /// Destination URL. Constraints: https scheme; non-private, non-loopback
4988 /// host. Validation failures return `invalid_argument`.
4989 #[prost(string, tag="2")]
4990 pub url: ::prost::alloc::string::String,
4991 #[prost(bool, tag="3")]
4992 pub enabled: bool,
4993 /// Shared secret used for the `X-Pidgr-Signature` HMAC-SHA256 header.
4994 /// Write-only. Unset keeps the current secret; set rotates it.
4995 /// Constraints: 16–256 bytes when set.
4996 #[prost(string, optional, tag="4")]
4997 pub secret: ::core::option::Option<::prost::alloc::string::String>,
4998}
4999#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5000pub struct SetOrgWebhookConfigResponse {
5001 #[prost(string, tag="1")]
5002 pub org_id: ::prost::alloc::string::String,
5003 #[prost(string, tag="2")]
5004 pub url: ::prost::alloc::string::String,
5005 #[prost(bool, tag="3")]
5006 pub enabled: bool,
5007 #[prost(bool, tag="4")]
5008 pub has_secret: bool,
5009 #[prost(message, optional, tag="5")]
5010 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
5011 #[prost(message, optional, tag="6")]
5012 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
5013}
5014// ─── CreateChannelConnectLink ───────────────────────────────────────────────
5015
5016/// Mints a short-lived, HMAC-signed opt-in link a user follows to bind a
5017/// third-party channel to their (org, user). Only follow-style channels are
5018/// accepted: CHANNEL_NAME_TELEGRAM (bot-follow), CHANNEL_NAME_SLACK (OAuth),
5019/// CHANNEL_NAME_LINE (follow-code). Any other channel is rejected server-side
5020/// with `invalid_argument`. Wraps the pidgr-api `internal/linktoken` minter.
5021#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5022pub struct CreateChannelConnectLinkRequest {
5023 #[prost(string, tag="1")]
5024 pub org_id: ::prost::alloc::string::String,
5025 /// Internal user UUID; resolved via UserResolver on the server. The minted
5026 /// token binds the resulting channel identifier to this (org, user).
5027 #[prost(string, tag="2")]
5028 pub user_id: ::prost::alloc::string::String,
5029 /// Channel to connect. Constraints: must be one of CHANNEL_NAME_TELEGRAM,
5030 /// CHANNEL_NAME_SLACK, CHANNEL_NAME_LINE. Other values return
5031 /// `invalid_argument`.
5032 #[prost(enumeration="ChannelName", tag="3")]
5033 pub channel: i32,
5034}
5035#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5036pub struct CreateChannelConnectLinkResponse {
5037 /// The deep link the client renders for the user to follow (e.g. a
5038 /// Telegram bot-follow URL, Slack OAuth authorize URL, or LINE follow URL).
5039 #[prost(string, tag="1")]
5040 pub connect_url: ::prost::alloc::string::String,
5041 /// The raw 64-char base64url opt-in token embedded in `connect_url`,
5042 /// surfaced separately so clients can render it as a QR code or copy
5043 /// button. Implementation detail — clients SHOULD NOT parse or mutate it.
5044 #[prost(string, tag="2")]
5045 pub token: ::prost::alloc::string::String,
5046 /// When the minted token expires. After this time the link no longer
5047 /// binds and the user must request a fresh one.
5048 #[prost(message, optional, tag="3")]
5049 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
5050}
5051// ─── CreateSlackWorkspaceInstallAuthorization ───────────────────────────────
5052
5053/// Mints a short-lived, HMAC-signed token authorizing a Slack WORKSPACE
5054/// install into the caller's AUTHORIZED org. The admin passes the token to the
5055/// pidgr-integrations install-start endpoint, which verifies it and installs
5056/// into the org the token binds — not the caller's JWT home org. This is the
5057/// workspace-install analogue of CreateChannelConnectLink (which binds the
5058/// per-user link flow): without it, a multi-org admin who selects a non-home
5059/// org still installs the bot into their home org, because the install-start
5060/// endpoint has no Cognito-sub→internal-id resolver of its own and falls back
5061/// to the JWT org claim.
5062#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5063pub struct CreateSlackWorkspaceInstallAuthorizationRequest {
5064 /// Must equal the caller's authorized org (auth.OrgID) — cross-org minting is
5065 /// rejected with permission_denied.
5066 #[prost(string, tag="1")]
5067 pub org_id: ::prost::alloc::string::String,
5068}
5069#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5070pub struct CreateSlackWorkspaceInstallAuthorizationResponse {
5071 /// The opaque HMAC token the client passes as the `token` query parameter to
5072 /// the integrations `/webhooks/slack/oauth/install/start` endpoint. It binds
5073 /// the authorized (org, internal user id) and an expiry. Implementation
5074 /// detail — clients SHOULD NOT parse or mutate it.
5075 #[prost(string, tag="1")]
5076 pub token: ::prost::alloc::string::String,
5077 /// When the minted token expires. After this the admin must request a fresh
5078 /// one before starting the install.
5079 #[prost(message, optional, tag="2")]
5080 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
5081}
5082// ─── Messages ───────────────────────────────────────────────────────────────
5083
5084/// A shareable invite link that allows users to self-join an organization.
5085/// Links carry a role assignment and optional usage/expiry constraints.
5086#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5087pub struct InviteLink {
5088 /// Unique identifier for the invite link.
5089 #[prost(string, tag="1")]
5090 pub id: ::prost::alloc::string::String,
5091 /// Cryptographically random base64url-encoded token (43 characters).
5092 #[prost(string, tag="2")]
5093 pub token: ::prost::alloc::string::String,
5094 /// ID of the role assigned to users who redeem this link.
5095 #[prost(string, tag="3")]
5096 pub role_id: ::prost::alloc::string::String,
5097 /// Maximum number of times this link can be redeemed.
5098 /// 0 means unlimited.
5099 #[prost(int32, tag="4")]
5100 pub max_uses: i32,
5101 /// Number of times this link has been redeemed.
5102 #[prost(int32, tag="5")]
5103 pub use_count: i32,
5104 /// When the link expires. Empty if no expiry.
5105 #[prost(message, optional, tag="6")]
5106 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
5107 /// When the link was revoked. Empty if not revoked.
5108 #[prost(message, optional, tag="7")]
5109 pub revoked_at: ::core::option::Option<::prost_types::Timestamp>,
5110 /// ID of the admin who created the link.
5111 #[prost(string, tag="8")]
5112 pub created_by: ::prost::alloc::string::String,
5113 /// When the link was created.
5114 #[prost(message, optional, tag="9")]
5115 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
5116 /// Data governance region assigned to users who redeem this link. Empty means inherit from org default.
5117 /// Valid values: EU, LATAM, BR, APAC, US.
5118 #[prost(string, tag="10")]
5119 pub data_governance_region: ::prost::alloc::string::String,
5120}
5121/// Request to create a new invite link for the organization.
5122#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5123pub struct CreateInviteLinkRequest {
5124 /// ID of the role to assign. Defaults to the organization's employee role if empty.
5125 #[prost(string, tag="1")]
5126 pub role_id: ::prost::alloc::string::String,
5127 /// Maximum number of redemptions. 0 means unlimited.
5128 #[prost(int32, tag="2")]
5129 pub max_uses: i32,
5130 /// Number of hours until the link expires. 0 means no expiry.
5131 /// Constraints: Valid range 0 to 8760 (1 year).
5132 #[prost(int32, tag="3")]
5133 pub expires_in_hours: i32,
5134 /// Optional data governance region. Users who redeem this link inherit this region. Empty means inherit from org default.
5135 /// Valid values: EU, LATAM, BR, APAC, US.
5136 #[prost(string, tag="4")]
5137 pub data_governance_region: ::prost::alloc::string::String,
5138}
5139/// Response after creating an invite link.
5140#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5141pub struct CreateInviteLinkResponse {
5142 /// The newly created invite link.
5143 #[prost(message, optional, tag="1")]
5144 pub invite_link: ::core::option::Option<InviteLink>,
5145 /// Full URL for sharing (e.g. "<https://app.pidgr.com/join?token=<TOKEN>">).
5146 #[prost(string, tag="2")]
5147 pub url: ::prost::alloc::string::String,
5148}
5149/// Request to list all invite links for the organization.
5150#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5151pub struct ListInviteLinksRequest {
5152}
5153/// Response containing all invite links for the organization.
5154#[derive(Clone, PartialEq, ::prost::Message)]
5155pub struct ListInviteLinksResponse {
5156 /// All invite links (active, expired, maxed-out, and revoked), ordered by creation date descending.
5157 #[prost(message, repeated, tag="1")]
5158 pub invite_links: ::prost::alloc::vec::Vec<InviteLink>,
5159}
5160/// Request to revoke an invite link.
5161#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5162pub struct RevokeInviteLinkRequest {
5163 /// ID of the invite link to revoke. Required.
5164 #[prost(string, tag="1")]
5165 pub invite_link_id: ::prost::alloc::string::String,
5166}
5167/// Response after revoking an invite link.
5168#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5169pub struct RevokeInviteLinkResponse {
5170}
5171/// Request to redeem an invite link (authenticated — email extracted from JWT).
5172#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5173pub struct RedeemInviteLinkRequest {
5174 /// The invite link token from the URL query parameter.
5175 #[prost(string, tag="1")]
5176 pub token: ::prost::alloc::string::String,
5177}
5178/// Response after redeeming an invite link.
5179#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5180pub struct RedeemInviteLinkResponse {
5181 /// Name of the organization the user was added to.
5182 #[prost(string, tag="1")]
5183 pub organization_name: ::prost::alloc::string::String,
5184}
5185/// Request to validate an invite link and provision a user account if needed (unauthenticated).
5186#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5187pub struct ValidateInviteLinkRequest {
5188 /// The invite link token from the URL query parameter.
5189 #[prost(string, tag="1")]
5190 pub token: ::prost::alloc::string::String,
5191 /// Email address of the user joining the organization.
5192 /// Constraints: Max length 254 characters (RFC 5321).
5193 #[prost(string, tag="2")]
5194 pub email: ::prost::alloc::string::String,
5195}
5196/// Response after validating an invite link.
5197#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5198pub struct ValidateInviteLinkResponse {
5199 /// Name of the organization the invite link belongs to.
5200 #[prost(string, tag="1")]
5201 pub organization_name: ::prost::alloc::string::String,
5202}
5203// ─── Messages ───────────────────────────────────────────────────────────────
5204
5205/// Request to invite a new user to the organization.
5206#[derive(Clone, PartialEq, ::prost::Message)]
5207pub struct InviteUserRequest {
5208 /// Email address to send the invitation to.
5209 /// Constraints: Max length 254 characters (RFC 5321).
5210 #[prost(string, tag="1")]
5211 pub email: ::prost::alloc::string::String,
5212 /// Display name for the invited user.
5213 /// Constraints: Max length 200 characters.
5214 #[prost(string, tag="2")]
5215 pub name: ::prost::alloc::string::String,
5216 /// ID of the role to assign. Defaults to the organization's employee role if empty.
5217 #[prost(string, tag="4")]
5218 pub role_id: ::prost::alloc::string::String,
5219 /// Optional profile attributes to pre-fill at invitation time.
5220 #[prost(message, optional, tag="5")]
5221 pub profile: ::core::option::Option<UserProfile>,
5222 /// Optional data governance region for the invited user. Empty means inherit from org default.
5223 /// Valid values: EU, LATAM, BR, APAC, US.
5224 #[prost(string, tag="6")]
5225 pub data_governance_region: ::prost::alloc::string::String,
5226}
5227/// Response after inviting a user.
5228#[derive(Clone, PartialEq, ::prost::Message)]
5229pub struct InviteUserResponse {
5230 /// The newly created user (status: INVITED).
5231 #[prost(message, optional, tag="1")]
5232 pub user: ::core::option::Option<User>,
5233}
5234/// Request to retrieve a user by ID.
5235#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5236pub struct GetUserRequest {
5237 /// ID of the user to retrieve.
5238 #[prost(string, tag="1")]
5239 pub user_id: ::prost::alloc::string::String,
5240}
5241/// Response containing the requested user.
5242#[derive(Clone, PartialEq, ::prost::Message)]
5243pub struct GetUserResponse {
5244 /// The requested user.
5245 #[prost(message, optional, tag="1")]
5246 pub user: ::core::option::Option<User>,
5247}
5248/// Request to list users in the organization with pagination.
5249#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5250pub struct ListUsersRequest {
5251 /// Pagination parameters.
5252 #[prost(message, optional, tag="1")]
5253 pub pagination: ::core::option::Option<Pagination>,
5254}
5255/// Response containing a page of users.
5256#[derive(Clone, PartialEq, ::prost::Message)]
5257pub struct ListUsersResponse {
5258 /// List of users in this page.
5259 #[prost(message, repeated, tag="1")]
5260 pub users: ::prost::alloc::vec::Vec<User>,
5261 /// Pagination metadata for fetching subsequent pages.
5262 #[prost(message, optional, tag="2")]
5263 pub pagination_meta: ::core::option::Option<PaginationMeta>,
5264}
5265/// Request to change a user's role within the organization.
5266#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5267pub struct UpdateUserRoleRequest {
5268 /// ID of the user whose role to update.
5269 #[prost(string, tag="1")]
5270 pub user_id: ::prost::alloc::string::String,
5271 /// ID of the new role to assign.
5272 #[prost(string, tag="2")]
5273 pub role_id: ::prost::alloc::string::String,
5274}
5275/// Response after updating a user's role.
5276#[derive(Clone, PartialEq, ::prost::Message)]
5277pub struct UpdateUserRoleResponse {
5278 /// The updated user with the new role.
5279 #[prost(message, optional, tag="1")]
5280 pub user: ::core::option::Option<User>,
5281}
5282/// Request to deactivate a user within the organization.
5283#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5284pub struct DeactivateUserRequest {
5285 /// ID of the user to deactivate.
5286 #[prost(string, tag="1")]
5287 pub user_id: ::prost::alloc::string::String,
5288}
5289/// Response after deactivating a user.
5290#[derive(Clone, PartialEq, ::prost::Message)]
5291pub struct DeactivateUserResponse {
5292 /// The deactivated user (status: DEACTIVATED).
5293 #[prost(message, optional, tag="1")]
5294 pub user: ::core::option::Option<User>,
5295}
5296/// Request to reactivate a deactivated user.
5297#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5298pub struct ReactivateUserRequest {
5299 /// ID of the user to reactivate.
5300 #[prost(string, tag="1")]
5301 pub user_id: ::prost::alloc::string::String,
5302}
5303/// Response after reactivating a user.
5304#[derive(Clone, PartialEq, ::prost::Message)]
5305pub struct ReactivateUserResponse {
5306 /// The reactivated user (status: INVITED).
5307 #[prost(message, optional, tag="1")]
5308 pub user: ::core::option::Option<User>,
5309}
5310/// Request to revoke an invitation for a user who has not yet registered.
5311#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5312pub struct RevokeInviteRequest {
5313 /// ID of the invited user to remove.
5314 /// Constraints: UUID format (36 characters).
5315 #[prost(string, tag="1")]
5316 pub user_id: ::prost::alloc::string::String,
5317}
5318/// Response after revoking an invitation. Empty on success.
5319#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5320pub struct RevokeInviteResponse {
5321}
5322/// Request to update a user's profile attributes.
5323#[derive(Clone, PartialEq, ::prost::Message)]
5324pub struct UpdateUserProfileRequest {
5325 /// ID of the user whose profile to update.
5326 /// Empty or matching the caller's own ID allows self-update without PERMISSION_MEMBERS_MANAGE.
5327 #[prost(string, tag="1")]
5328 pub user_id: ::prost::alloc::string::String,
5329 /// Profile attributes to set. All provided fields overwrite existing values.
5330 #[prost(message, optional, tag="2")]
5331 pub profile: ::core::option::Option<UserProfile>,
5332}
5333/// Response after updating a user's profile.
5334#[derive(Clone, PartialEq, ::prost::Message)]
5335pub struct UpdateUserProfileResponse {
5336 /// The updated user with the new profile.
5337 #[prost(message, optional, tag="1")]
5338 pub user: ::core::option::Option<User>,
5339}
5340/// Request to retrieve the caller's platform settings.
5341#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5342pub struct GetUserSettingsRequest {
5343}
5344/// Response containing the caller's platform settings.
5345#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5346pub struct GetUserSettingsResponse {
5347 /// Current settings. Fields at their default value indicate the platform default.
5348 #[prost(message, optional, tag="1")]
5349 pub settings: ::core::option::Option<UserSettings>,
5350}
5351/// Request to update the caller's platform settings.
5352#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5353pub struct UpdateUserSettingsRequest {
5354 /// Settings to update. Only fields with non-default (non-UNSPECIFIED) values
5355 /// are applied; default-valued fields are left unchanged.
5356 #[prost(message, optional, tag="1")]
5357 pub settings: ::core::option::Option<UserSettings>,
5358}
5359/// Response after updating the caller's platform settings.
5360#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5361pub struct UpdateUserSettingsResponse {
5362 /// The full settings after the update.
5363 #[prost(message, optional, tag="1")]
5364 pub settings: ::core::option::Option<UserSettings>,
5365}
5366/// Request to invite multiple users to the organization in a single call.
5367#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5368pub struct BulkInviteUsersRequest {
5369 /// Email addresses to invite.
5370 /// Constraints: Min 1, max 100 emails. Duplicates are deduplicated before processing.
5371 #[prost(string, repeated, tag="1")]
5372 pub emails: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
5373 /// ID of the role to assign. Defaults to the organization's employee role if empty.
5374 #[prost(string, tag="2")]
5375 pub role_id: ::prost::alloc::string::String,
5376}
5377/// Per-email result within a bulk invite operation.
5378#[derive(Clone, PartialEq, ::prost::Message)]
5379pub struct BulkInviteResult {
5380 /// The email address that was processed.
5381 #[prost(string, tag="1")]
5382 pub email: ::prost::alloc::string::String,
5383 /// Whether the invitation succeeded.
5384 #[prost(bool, tag="2")]
5385 pub success: bool,
5386 /// Error message if the invitation failed (e.g. "user already exists").
5387 /// Empty on success.
5388 #[prost(string, tag="3")]
5389 pub error: ::prost::alloc::string::String,
5390 /// The created user. Only set on success.
5391 #[prost(message, optional, tag="4")]
5392 pub user: ::core::option::Option<User>,
5393}
5394/// Response after bulk inviting users.
5395#[derive(Clone, PartialEq, ::prost::Message)]
5396pub struct BulkInviteUsersResponse {
5397 /// Per-email results in the same order as the deduplicated input.
5398 #[prost(message, repeated, tag="1")]
5399 pub results: ::prost::alloc::vec::Vec<BulkInviteResult>,
5400 /// Number of users successfully invited.
5401 #[prost(int32, tag="2")]
5402 pub invited_count: i32,
5403 /// Number of emails that failed.
5404 #[prost(int32, tag="3")]
5405 pub failed_count: i32,
5406}
5407/// Request to confirm passkey enrollment after client-side WebAuthn registration.
5408/// The server verifies that the caller has at least one registered WebAuthn
5409/// credential before setting the enrollment attribute.
5410#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5411pub struct ConfirmPasskeyEnrollmentRequest {
5412}
5413/// Response after confirming passkey enrollment.
5414#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5415pub struct ConfirmPasskeyEnrollmentResponse {
5416 /// Whether enrollment was confirmed and the user attribute was updated.
5417 #[prost(bool, tag="1")]
5418 pub confirmed: bool,
5419}
5420/// Request to update a user's data governance region.
5421#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5422pub struct UpdateUserRegionRequest {
5423 /// ID of the user whose region to update. Required.
5424 #[prost(string, tag="1")]
5425 pub user_id: ::prost::alloc::string::String,
5426 /// New governance region, or empty to inherit from org default.
5427 /// Valid values: EU, LATAM, BR, APAC, US.
5428 #[prost(string, tag="2")]
5429 pub data_governance_region: ::prost::alloc::string::String,
5430}
5431/// Response after updating a user's governance region.
5432#[derive(Clone, PartialEq, ::prost::Message)]
5433pub struct UpdateUserRegionResponse {
5434 /// The updated user.
5435 #[prost(message, optional, tag="1")]
5436 pub user: ::core::option::Option<User>,
5437 /// Temporal workflow ID for the region migration, if a migration was triggered.
5438 /// Empty if the region didn't actually change.
5439 #[prost(string, tag="2")]
5440 pub migration_workflow_id: ::prost::alloc::string::String,
5441}
5442// ─── Messages ───────────────────────────────────────────────────────────────
5443
5444/// A qualitative statement of a state the organization wants to hold
5445/// true. Owned by the organization, never by a single campaign. Content
5446/// is always authored by the organization; the contract only carries
5447/// structure.
5448#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5449pub struct Objective {
5450 /// Unique identifier for the objective.
5451 #[prost(string, tag="1")]
5452 pub id: ::prost::alloc::string::String,
5453 /// Whether this is a standing objective or a time-bounded initiative.
5454 #[prost(enumeration="ObjectiveKind", tag="2")]
5455 pub kind: i32,
5456 /// The statement itself. Required.
5457 /// Constraints: Max length 300 characters.
5458 #[prost(string, tag="3")]
5459 pub title: ::prost::alloc::string::String,
5460 /// Longer explanation of what the statement means and does not mean.
5461 /// Constraints: Max length 4000 characters.
5462 #[prost(string, tag="4")]
5463 pub description: ::prost::alloc::string::String,
5464 /// ID of the user accountable for the objective. Optional.
5465 #[prost(string, tag="5")]
5466 pub owner_user_id: ::prost::alloc::string::String,
5467 /// Lifecycle state.
5468 #[prost(enumeration="ObjectiveState", tag="6")]
5469 pub state: i32,
5470 /// For an initiative, the standing objective it contributes to. Empty
5471 /// when the initiative stands alone, and always empty for
5472 /// OBJECTIVE_KIND_OBJECTIVE.
5473 #[prost(string, tag="7")]
5474 pub parent_objective_id: ::prost::alloc::string::String,
5475 /// For an initiative, the date it is expected to end. Unset for a
5476 /// standing objective, which by definition does not have one.
5477 #[prost(message, optional, tag="8")]
5478 pub ends_at: ::core::option::Option<::prost_types::Timestamp>,
5479 /// Number of indicators currently attached.
5480 #[prost(int32, tag="9")]
5481 pub indicator_count: i32,
5482 /// Timestamp when the objective was created.
5483 #[prost(message, optional, tag="10")]
5484 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
5485 /// Timestamp when the objective was last updated.
5486 #[prost(message, optional, tag="11")]
5487 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
5488}
5489/// A form problem found in an objective's wording, returned alongside the
5490/// stored objective. Never blocks the write.
5491#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5492pub struct ObjectiveAdvisory {
5493 /// Which form problem was detected.
5494 #[prost(enumeration="ObjectiveWritingIssue", tag="1")]
5495 pub issue: i32,
5496 /// Plain-language explanation of what was detected and why it matters.
5497 #[prost(string, tag="2")]
5498 pub detail: ::prost::alloc::string::String,
5499 /// A rewrite the author can accept or ignore. May be empty when no
5500 /// rewrite could be produced.
5501 #[prost(string, tag="3")]
5502 pub suggested_rewrite: ::prost::alloc::string::String,
5503}
5504/// Something the author should know before relying on a verification
5505/// campaign as an indicator's evidence, returned alongside the stored
5506/// indicator. Never blocks the write.
5507///
5508/// Asking a verifier about a unit rather than about each of its members
5509/// is what keeps a stored answer from being one person's judgement of
5510/// another. That protection is a function of size: below a handful of
5511/// people, a statement about the unit is in practice a statement about
5512/// each member, and the distinction reconstructs itself. The platform
5513/// responds by putting the question to the level above instead, and where
5514/// there is no level above, the objective simply gets no evidence by this
5515/// route.
5516///
5517/// The notice states that consequence to the admin, who is the one who
5518/// can change the shape of the question or decide it is acceptable. It is
5519/// deliberately not a warning shown to the verifier at the moment of
5520/// answering: that would claim a safeguard that does not exist, and would
5521/// ask one person to accept a risk that runs to somebody else.
5522#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5523pub struct VerificationSetupNotice {
5524 /// What follows from the current configuration, in plain language.
5525 #[prost(string, tag="1")]
5526 pub detail: ::prost::alloc::string::String,
5527 /// How many of the units this derivation would reach are smaller than
5528 /// the floor.
5529 #[prost(int32, tag="2")]
5530 pub units_below_floor: i32,
5531 /// The size at or above which a unit is asked about on its own.
5532 #[prost(int32, tag="3")]
5533 pub unit_floor: i32,
5534}
5535/// A declared way of observing whether an objective holds. Several per
5536/// objective is the intended shape: indicators are individually
5537/// incomplete and are meant to compensate for one another.
5538#[derive(Clone, PartialEq, ::prost::Message)]
5539pub struct Indicator {
5540 /// Unique identifier for the indicator.
5541 #[prost(string, tag="1")]
5542 pub id: ::prost::alloc::string::String,
5543 /// Objective this indicator hangs from.
5544 #[prost(string, tag="2")]
5545 pub objective_id: ::prost::alloc::string::String,
5546 /// Short name for the indicator. Required.
5547 /// Constraints: Max length 200 characters.
5548 #[prost(string, tag="3")]
5549 pub name: ::prost::alloc::string::String,
5550 /// Unit the readings are expressed in (e.g. "percent", "days",
5551 /// "incidents"). Free text so that existing measures can be carried
5552 /// over unchanged.
5553 /// Constraints: Max length 50 characters.
5554 #[prost(string, tag="4")]
5555 pub unit: ::prost::alloc::string::String,
5556 /// Which direction of movement is the desired one.
5557 #[prost(enumeration="IndicatorDirection", tag="5")]
5558 pub direction: i32,
5559 /// How often a reading is expected.
5560 #[prost(enumeration="IndicatorFrequency", tag="6")]
5561 pub frequency: i32,
5562 /// ID of the user accountable for the indicator. Optional.
5563 #[prost(string, tag="7")]
5564 pub owner_user_id: ::prost::alloc::string::String,
5565 /// Where readings come from. Required.
5566 #[prost(message, optional, tag="8")]
5567 pub evidence_source: ::core::option::Option<EvidenceSource>,
5568 /// Why this indicator was chosen over the alternatives.
5569 /// Constraints: Max length 2000 characters.
5570 #[prost(string, tag="9")]
5571 pub rationale: ::prost::alloc::string::String,
5572 /// What the indicator is meant to say about the objective.
5573 /// Constraints: Max length 2000 characters.
5574 #[prost(string, tag="10")]
5575 pub strategic_meaning: ::prost::alloc::string::String,
5576 /// How a reading should be read, including what it does not cover.
5577 /// Constraints: Max length 2000 characters.
5578 #[prost(string, tag="11")]
5579 pub interpretation_guidance: ::prost::alloc::string::String,
5580 /// The behaviour this indicator could encourage if it were optimized
5581 /// on its own. Pre-filled by the server where a structural weakness in
5582 /// the evidence source implies one, always editable, never required.
5583 /// Constraints: Max length 2000 characters.
5584 #[prost(string, tag="12")]
5585 pub perverse_behavior_note: ::prost::alloc::string::String,
5586 /// Whether any reading has ever corroborated this indicator.
5587 #[prost(enumeration="IndicatorVerificationState", tag="13")]
5588 pub verification_state: i32,
5589 /// Timestamp when the indicator was created.
5590 #[prost(message, optional, tag="14")]
5591 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
5592 /// Timestamp when the indicator was last updated.
5593 #[prost(message, optional, tag="15")]
5594 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
5595 /// The value the organization is aiming for, expressed in `unit` and
5596 /// read together with `direction`. Absent when no target has been set.
5597 ///
5598 /// Targets live here rather than inside the objective's wording, and
5599 /// they sit at the routine tier of change: revising a target is
5600 /// expected housekeeping, unlike rewriting the objective it serves.
5601 #[prost(double, optional, tag="16")]
5602 pub target: ::core::option::Option<f64>,
5603}
5604/// Where an indicator's readings come from, plus the structural facts
5605/// that follow from that choice. The facts are descriptive, not a score:
5606/// they state what the configuration implies so the reader can judge it,
5607/// and are never combined into a single rating.
5608#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5609pub struct EvidenceSource {
5610 /// Which adapter produces the readings.
5611 #[prost(enumeration="EvidenceSourceKind", tag="1")]
5612 pub kind: i32,
5613 /// True when whoever reports the reading is also whoever the reading
5614 /// is about. Self-reported readings can be negotiated rather than
5615 /// produced.
5616 #[prost(bool, tag="2")]
5617 pub reporter_is_subject: bool,
5618 /// Whether the source observes the whole population or a sample.
5619 #[prost(enumeration="EvidenceCoverage", tag="3")]
5620 pub coverage: i32,
5621 /// True when a party other than the reporter could check the reading
5622 /// against an independent record.
5623 #[prost(bool, tag="4")]
5624 pub third_party_verifiable: bool,
5625 /// Adapter-specific configuration. Must match `kind`.
5626 #[prost(oneof="evidence_source::Detail", tags="5, 6, 7, 8")]
5627 pub detail: ::core::option::Option<evidence_source::Detail>,
5628}
5629/// Nested message and enum types in `EvidenceSource`.
5630pub mod evidence_source {
5631 /// Adapter-specific configuration. Must match `kind`.
5632 #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)]
5633 pub enum Detail {
5634 #[prost(message, tag="5")]
5635 InApp(super::InAppEvidence),
5636 #[prost(message, tag="6")]
5637 VerificationCampaign(super::VerificationCampaignEvidence),
5638 #[prost(message, tag="7")]
5639 Webhook(super::WebhookEvidence),
5640 #[prost(message, tag="8")]
5641 ManualEntry(super::ManualEntryEvidence),
5642 }
5643}
5644/// Configuration for readings produced inside the product by the
5645/// audience of the message itself.
5646#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5647pub struct InAppEvidence {
5648 /// Which response counts as a reading. ActionType currently defines
5649 /// only ACK; poll answers, go-to confirmations and attestations become
5650 /// expressible here once message actions land in common.proto.
5651 #[prost(enumeration="ActionType", tag="1")]
5652 pub action_type: i32,
5653}
5654/// Configuration for readings produced by a deferred follow-up message
5655/// sent to someone other than the audience.
5656#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5657pub struct VerificationCampaignEvidence {
5658 /// How the recipients of the follow-up are derived from the audience
5659 /// being verified. Kinds other than the ones enumerated are rejected
5660 /// with UNIMPLEMENTED.
5661 #[prost(enumeration="VerifierDerivation", tag="1")]
5662 pub verifier_derivation: i32,
5663 /// Days to wait after the original message before the follow-up is
5664 /// sent.
5665 #[prost(int32, tag="2")]
5666 pub delay_days: i32,
5667 /// Template used for the follow-up. Optional; a default is used when
5668 /// empty.
5669 #[prost(string, tag="3")]
5670 pub template_id: ::prost::alloc::string::String,
5671}
5672/// Configuration for readings the organization pushes from one of its
5673/// own systems.
5674#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5675pub struct WebhookEvidence {
5676 /// Name of the system the readings come from. Required for this
5677 /// adapter.
5678 /// Constraints: Max length 200 characters.
5679 #[prost(string, tag="1")]
5680 pub system_name: ::prost::alloc::string::String,
5681 /// How the reading is produced in that system, in the organization's
5682 /// own words.
5683 /// Constraints: Max length 2000 characters.
5684 #[prost(string, tag="2")]
5685 pub description: ::prost::alloc::string::String,
5686}
5687/// Configuration for readings entered by hand or imported from a
5688/// spreadsheet. There is no originating system to name — a person is the
5689/// source.
5690#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5691pub struct ManualEntryEvidence {
5692 /// How the reading is arrived at before it is entered, in the
5693 /// organization's own words.
5694 /// Constraints: Max length 2000 characters.
5695 #[prost(string, tag="1")]
5696 pub description: ::prost::alloc::string::String,
5697}
5698/// Declares which objective a campaign serves. The link is what turns a
5699/// campaign's response rate from a result in itself into evidence about
5700/// something the organization was trying to achieve.
5701#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5702pub struct CampaignObjectiveLink {
5703 /// Campaign that serves the objective.
5704 #[prost(string, tag="1")]
5705 pub campaign_id: ::prost::alloc::string::String,
5706 /// Objective the campaign serves.
5707 #[prost(string, tag="2")]
5708 pub objective_id: ::prost::alloc::string::String,
5709 /// How the link came to be.
5710 #[prost(enumeration="LinkOrigin", tag="3")]
5711 pub origin: i32,
5712 /// Timestamp when the link was recorded.
5713 #[prost(message, optional, tag="4")]
5714 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
5715}
5716/// Request to create an objective.
5717#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5718pub struct CreateObjectiveRequest {
5719 /// The statement. Required.
5720 /// Constraints: Max length 300 characters.
5721 #[prost(string, tag="1")]
5722 pub title: ::prost::alloc::string::String,
5723 /// Longer explanation. Optional.
5724 /// Constraints: Max length 4000 characters.
5725 #[prost(string, tag="2")]
5726 pub description: ::prost::alloc::string::String,
5727 /// Accountable user. Optional.
5728 #[prost(string, tag="3")]
5729 pub owner_user_id: ::prost::alloc::string::String,
5730 /// Standing objective or time-bounded initiative. Defaults to
5731 /// OBJECTIVE_KIND_OBJECTIVE when unspecified.
5732 #[prost(enumeration="ObjectiveKind", tag="4")]
5733 pub kind: i32,
5734 /// For an initiative, the standing objective it contributes to.
5735 /// Optional; must be empty for a standing objective.
5736 #[prost(string, tag="5")]
5737 pub parent_objective_id: ::prost::alloc::string::String,
5738 /// For an initiative, its expected end. Must be unset for a standing
5739 /// objective.
5740 #[prost(message, optional, tag="6")]
5741 pub ends_at: ::core::option::Option<::prost_types::Timestamp>,
5742 /// Initial lifecycle state. Defaults to OBJECTIVE_STATE_DRAFT when
5743 /// unspecified. OBJECTIVE_STATE_ARCHIVED is rejected.
5744 #[prost(enumeration="ObjectiveState", tag="7")]
5745 pub state: i32,
5746}
5747/// Response after creating an objective.
5748#[derive(Clone, PartialEq, ::prost::Message)]
5749pub struct CreateObjectiveResponse {
5750 /// The newly created objective. Always present, including when
5751 /// advisories were raised.
5752 #[prost(message, optional, tag="1")]
5753 pub objective: ::core::option::Option<Objective>,
5754 /// Form problems found in the wording. Advisory only — the objective
5755 /// was stored regardless.
5756 #[prost(message, repeated, tag="2")]
5757 pub advisories: ::prost::alloc::vec::Vec<ObjectiveAdvisory>,
5758}
5759/// Request to update an objective.
5760///
5761/// Every mutable field carries explicit presence and they all follow one
5762/// rule: a field left absent leaves the stored value untouched, and a
5763/// field that is present replaces it — including when the value sent is
5764/// empty. Clearing a field is therefore expressible, which matters for
5765/// text an author wants gone rather than merely reworded.
5766#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5767pub struct UpdateObjectiveRequest {
5768 /// ID of the objective to update. Required.
5769 #[prost(string, tag="1")]
5770 pub objective_id: ::prost::alloc::string::String,
5771 /// New statement.
5772 /// Constraints: Max length 300 characters.
5773 #[prost(string, optional, tag="2")]
5774 pub title: ::core::option::Option<::prost::alloc::string::String>,
5775 /// New explanation.
5776 /// Constraints: Max length 4000 characters.
5777 #[prost(string, optional, tag="3")]
5778 pub description: ::core::option::Option<::prost::alloc::string::String>,
5779 /// New accountable user. Present and empty detaches the owner.
5780 #[prost(string, optional, tag="4")]
5781 pub owner_user_id: ::core::option::Option<::prost::alloc::string::String>,
5782 /// New lifecycle state. Archiving an objective is done here, by
5783 /// sending OBJECTIVE_STATE_ARCHIVED.
5784 #[prost(enumeration="ObjectiveState", optional, tag="5")]
5785 pub state: ::core::option::Option<i32>,
5786 /// New expected end for an initiative. Reclassifying to
5787 /// OBJECTIVE_KIND_OBJECTIVE clears it regardless of what is sent here,
5788 /// since a standing objective has no end.
5789 #[prost(message, optional, tag="6")]
5790 pub ends_at: ::core::option::Option<::prost_types::Timestamp>,
5791 /// Reclassify between a standing objective and a time-bounded
5792 /// initiative, so that an OBJECTIVE_WRITING_ISSUE_PROJECT_FORM
5793 /// advisory can be acted on without recreating the entry.
5794 #[prost(enumeration="ObjectiveKind", optional, tag="7")]
5795 pub kind: ::core::option::Option<i32>,
5796 /// For an initiative, the standing objective it contributes to.
5797 /// Present and empty detaches it and leaves the initiative standing
5798 /// alone.
5799 #[prost(string, optional, tag="8")]
5800 pub parent_objective_id: ::core::option::Option<::prost::alloc::string::String>,
5801}
5802/// Response after updating an objective.
5803#[derive(Clone, PartialEq, ::prost::Message)]
5804pub struct UpdateObjectiveResponse {
5805 /// The updated objective.
5806 #[prost(message, optional, tag="1")]
5807 pub objective: ::core::option::Option<Objective>,
5808 /// Form problems found in the new wording. Advisory only — the update
5809 /// was applied regardless.
5810 #[prost(message, repeated, tag="2")]
5811 pub advisories: ::prost::alloc::vec::Vec<ObjectiveAdvisory>,
5812}
5813/// Request to retrieve one objective with its indicators.
5814#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5815pub struct GetObjectiveRequest {
5816 /// ID of the objective to retrieve. Required.
5817 #[prost(string, tag="1")]
5818 pub objective_id: ::prost::alloc::string::String,
5819}
5820/// Response containing the requested objective.
5821#[derive(Clone, PartialEq, ::prost::Message)]
5822pub struct GetObjectiveResponse {
5823 /// The requested objective.
5824 #[prost(message, optional, tag="1")]
5825 pub objective: ::core::option::Option<Objective>,
5826 /// Indicators attached to it, ordered by creation time.
5827 #[prost(message, repeated, tag="2")]
5828 pub indicators: ::prost::alloc::vec::Vec<Indicator>,
5829}
5830/// Request to list the organization's objectives with pagination.
5831#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5832pub struct ListObjectivesRequest {
5833 /// Pagination parameters.
5834 #[prost(message, optional, tag="1")]
5835 pub pagination: ::core::option::Option<Pagination>,
5836 /// Return only objectives in this state. Unspecified returns every
5837 /// state except OBJECTIVE_STATE_ARCHIVED.
5838 #[prost(enumeration="ObjectiveState", tag="2")]
5839 pub state: i32,
5840 /// Return only entries of this kind. Unspecified returns both kinds.
5841 #[prost(enumeration="ObjectiveKind", tag="3")]
5842 pub kind: i32,
5843}
5844/// Response containing a page of objectives.
5845#[derive(Clone, PartialEq, ::prost::Message)]
5846pub struct ListObjectivesResponse {
5847 /// Objectives in this page.
5848 #[prost(message, repeated, tag="1")]
5849 pub objectives: ::prost::alloc::vec::Vec<Objective>,
5850 /// Pagination metadata for fetching subsequent pages.
5851 #[prost(message, optional, tag="2")]
5852 pub pagination_meta: ::core::option::Option<PaginationMeta>,
5853}
5854/// Request to attach an indicator to an objective.
5855#[derive(Clone, PartialEq, ::prost::Message)]
5856pub struct AddIndicatorRequest {
5857 /// Objective the indicator hangs from. Required.
5858 #[prost(string, tag="1")]
5859 pub objective_id: ::prost::alloc::string::String,
5860 /// Short name. Required.
5861 /// Constraints: Max length 200 characters.
5862 #[prost(string, tag="2")]
5863 pub name: ::prost::alloc::string::String,
5864 /// Unit the readings are expressed in. Optional.
5865 /// Constraints: Max length 50 characters.
5866 #[prost(string, tag="3")]
5867 pub unit: ::prost::alloc::string::String,
5868 /// Desired direction of movement.
5869 #[prost(enumeration="IndicatorDirection", tag="4")]
5870 pub direction: i32,
5871 /// Expected reading cadence.
5872 #[prost(enumeration="IndicatorFrequency", tag="5")]
5873 pub frequency: i32,
5874 /// Accountable user. Optional.
5875 #[prost(string, tag="6")]
5876 pub owner_user_id: ::prost::alloc::string::String,
5877 /// Where readings come from. Required.
5878 #[prost(message, optional, tag="7")]
5879 pub evidence_source: ::core::option::Option<EvidenceSource>,
5880 /// Why this indicator was chosen. Optional.
5881 /// Constraints: Max length 2000 characters.
5882 #[prost(string, tag="8")]
5883 pub rationale: ::prost::alloc::string::String,
5884 /// What it is meant to say about the objective. Optional.
5885 /// Constraints: Max length 2000 characters.
5886 #[prost(string, tag="9")]
5887 pub strategic_meaning: ::prost::alloc::string::String,
5888 /// How a reading should be read. Optional.
5889 /// Constraints: Max length 2000 characters.
5890 #[prost(string, tag="10")]
5891 pub interpretation_guidance: ::prost::alloc::string::String,
5892 /// Behaviour the indicator could encourage if optimized on its own.
5893 /// Optional; the server pre-fills it when left empty and the evidence
5894 /// source implies one.
5895 /// Constraints: Max length 2000 characters.
5896 #[prost(string, tag="11")]
5897 pub perverse_behavior_note: ::prost::alloc::string::String,
5898 /// The value being aimed for, expressed in `unit`. Optional.
5899 #[prost(double, optional, tag="12")]
5900 pub target: ::core::option::Option<f64>,
5901}
5902/// Response after attaching an indicator.
5903#[derive(Clone, PartialEq, ::prost::Message)]
5904pub struct AddIndicatorResponse {
5905 /// The newly created indicator.
5906 #[prost(message, optional, tag="1")]
5907 pub indicator: ::core::option::Option<Indicator>,
5908 /// What follows from declaring a verification campaign as the evidence
5909 /// source, given the shape of the organization. Empty for every other
5910 /// evidence kind, and empty when nothing follows. Advisory only — the
5911 /// indicator was stored regardless.
5912 #[prost(message, repeated, tag="2")]
5913 pub notices: ::prost::alloc::vec::Vec<VerificationSetupNotice>,
5914}
5915/// Request to update an indicator.
5916///
5917/// Every mutable field carries explicit presence and they all follow one
5918/// rule: a field left absent leaves the stored value untouched, and a
5919/// field that is present replaces it — including when the value sent is
5920/// empty. This is what lets an author delete server-pre-filled text such
5921/// as `perverse_behavior_note` instead of only overwriting it.
5922#[derive(Clone, PartialEq, ::prost::Message)]
5923pub struct UpdateIndicatorRequest {
5924 /// ID of the indicator to update. Required.
5925 #[prost(string, tag="1")]
5926 pub indicator_id: ::prost::alloc::string::String,
5927 /// New name.
5928 /// Constraints: Max length 200 characters.
5929 #[prost(string, optional, tag="2")]
5930 pub name: ::core::option::Option<::prost::alloc::string::String>,
5931 /// New unit.
5932 /// Constraints: Max length 50 characters.
5933 #[prost(string, optional, tag="3")]
5934 pub unit: ::core::option::Option<::prost::alloc::string::String>,
5935 /// New direction.
5936 #[prost(enumeration="IndicatorDirection", optional, tag="4")]
5937 pub direction: ::core::option::Option<i32>,
5938 /// New cadence.
5939 #[prost(enumeration="IndicatorFrequency", optional, tag="5")]
5940 pub frequency: ::core::option::Option<i32>,
5941 /// New accountable user. Present and empty detaches the owner.
5942 #[prost(string, optional, tag="6")]
5943 pub owner_user_id: ::core::option::Option<::prost::alloc::string::String>,
5944 /// New evidence source.
5945 #[prost(message, optional, tag="7")]
5946 pub evidence_source: ::core::option::Option<EvidenceSource>,
5947 /// New rationale.
5948 /// Constraints: Max length 2000 characters.
5949 #[prost(string, optional, tag="8")]
5950 pub rationale: ::core::option::Option<::prost::alloc::string::String>,
5951 /// New strategic meaning.
5952 /// Constraints: Max length 2000 characters.
5953 #[prost(string, optional, tag="9")]
5954 pub strategic_meaning: ::core::option::Option<::prost::alloc::string::String>,
5955 /// New interpretation guidance.
5956 /// Constraints: Max length 2000 characters.
5957 #[prost(string, optional, tag="10")]
5958 pub interpretation_guidance: ::core::option::Option<::prost::alloc::string::String>,
5959 /// New note on encouraged behaviour. Present and empty deletes the
5960 /// note, which is how an author rejects the server's pre-filled text.
5961 /// Constraints: Max length 2000 characters.
5962 #[prost(string, optional, tag="11")]
5963 pub perverse_behavior_note: ::core::option::Option<::prost::alloc::string::String>,
5964 /// New target.
5965 #[prost(double, optional, tag="12")]
5966 pub target: ::core::option::Option<f64>,
5967}
5968/// Response after updating an indicator.
5969#[derive(Clone, PartialEq, ::prost::Message)]
5970pub struct UpdateIndicatorResponse {
5971 /// The updated indicator. Notices are recomputed on every update, so
5972 /// an evidence source switched onto or off a verification campaign
5973 /// gets the current answer rather than the one from creation time.
5974 #[prost(message, optional, tag="1")]
5975 pub indicator: ::core::option::Option<Indicator>,
5976 /// What follows from the evidence source as it now stands. Advisory
5977 /// only — the update was applied regardless.
5978 #[prost(message, repeated, tag="2")]
5979 pub notices: ::prost::alloc::vec::Vec<VerificationSetupNotice>,
5980}
5981/// Request to detach an indicator from its objective.
5982#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5983pub struct RemoveIndicatorRequest {
5984 /// ID of the indicator to remove. Required.
5985 #[prost(string, tag="1")]
5986 pub indicator_id: ::prost::alloc::string::String,
5987}
5988/// Response after removing an indicator.
5989#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
5990pub struct RemoveIndicatorResponse {
5991}
5992/// Request to declare that a campaign serves an objective.
5993#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
5994pub struct LinkCampaignToObjectiveRequest {
5995 /// Campaign to link. Required.
5996 #[prost(string, tag="1")]
5997 pub campaign_id: ::prost::alloc::string::String,
5998 /// Objective the campaign serves. Required.
5999 #[prost(string, tag="2")]
6000 pub objective_id: ::prost::alloc::string::String,
6001 /// How the link came to be. Defaults to LINK_ORIGIN_DECLARED when
6002 /// unspecified.
6003 #[prost(enumeration="LinkOrigin", tag="3")]
6004 pub origin: i32,
6005}
6006/// Response after linking a campaign to an objective.
6007#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6008pub struct LinkCampaignToObjectiveResponse {
6009 /// The recorded link. Linking an already-linked pair is idempotent and
6010 /// returns the existing link.
6011 #[prost(message, optional, tag="1")]
6012 pub link: ::core::option::Option<CampaignObjectiveLink>,
6013}
6014/// Request to remove the declaration that a campaign serves an objective.
6015#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6016pub struct UnlinkCampaignFromObjectiveRequest {
6017 /// Campaign to unlink. Required.
6018 #[prost(string, tag="1")]
6019 pub campaign_id: ::prost::alloc::string::String,
6020 /// Objective to unlink it from. Required.
6021 #[prost(string, tag="2")]
6022 pub objective_id: ::prost::alloc::string::String,
6023}
6024/// Response after unlinking a campaign from an objective.
6025#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
6026pub struct UnlinkCampaignFromObjectiveResponse {
6027}
6028/// Request to list campaign-to-objective links, from either end of the
6029/// relationship. Exactly one of `objective_id` and `campaign_id` must be
6030/// set; sending both, or neither, returns INVALID_ARGUMENT.
6031#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6032pub struct ListCampaignObjectiveLinksRequest {
6033 /// List the campaigns that serve this objective.
6034 #[prost(string, optional, tag="1")]
6035 pub objective_id: ::core::option::Option<::prost::alloc::string::String>,
6036 /// Pagination parameters.
6037 #[prost(message, optional, tag="2")]
6038 pub pagination: ::core::option::Option<Pagination>,
6039 /// List the objectives this campaign serves.
6040 #[prost(string, optional, tag="3")]
6041 pub campaign_id: ::core::option::Option<::prost::alloc::string::String>,
6042}
6043/// Response containing a page of campaign links.
6044#[derive(Clone, PartialEq, ::prost::Message)]
6045pub struct ListCampaignObjectiveLinksResponse {
6046 /// Links in this page, newest first.
6047 #[prost(message, repeated, tag="1")]
6048 pub links: ::prost::alloc::vec::Vec<CampaignObjectiveLink>,
6049 /// Pagination metadata for fetching subsequent pages.
6050 #[prost(message, optional, tag="2")]
6051 pub pagination_meta: ::core::option::Option<PaginationMeta>,
6052}
6053/// A candidate way of observing an objective, offered for a person to
6054/// accept, edit or throw away.
6055///
6056/// A suggestion is not an indicator and carries no identifier, because
6057/// nothing has been created. Proposing how an objective might be
6058/// observed is a bounded generative task and the platform is useful at
6059/// it; deciding that the proposed measure actually moves with the
6060/// objective is not something any model can settle, and only accumulated
6061/// readings can. Keeping the two apart is the point of this message
6062/// existing separately from Indicator.
6063#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6064pub struct IndicatorSuggestion {
6065 /// Proposed name for the indicator.
6066 #[prost(string, tag="1")]
6067 pub name: ::prost::alloc::string::String,
6068 /// Proposed unit the readings would be expressed in.
6069 #[prost(string, tag="2")]
6070 pub unit: ::prost::alloc::string::String,
6071 /// Proposed direction of desired movement.
6072 #[prost(enumeration="IndicatorDirection", tag="3")]
6073 pub direction: i32,
6074 /// Where readings would have to come from for this measure to exist.
6075 /// Part of the suggestion because a measure nobody can source is not a
6076 /// usable proposal.
6077 #[prost(enumeration="EvidenceSourceKind", tag="4")]
6078 pub evidence_source_kind: i32,
6079 /// Why this measure was proposed for this objective, in plain
6080 /// language, so the reader can reject it on the reasoning rather than
6081 /// on the wording.
6082 #[prost(string, tag="5")]
6083 pub rationale: ::prost::alloc::string::String,
6084}
6085/// Request for candidate indicators for a declared objective.
6086#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6087pub struct SuggestIndicatorsRequest {
6088 /// Objective to propose indicators for. Required.
6089 #[prost(string, tag="1")]
6090 pub objective_id: ::prost::alloc::string::String,
6091}
6092/// Response containing candidate indicators.
6093#[derive(Clone, PartialEq, ::prost::Message)]
6094pub struct SuggestIndicatorsResponse {
6095 /// Candidates, most relevant first. Never applied by the server —
6096 /// acting on one means calling AddIndicator with its contents, and the
6097 /// indicator that results is unverified like any other.
6098 ///
6099 /// Empty when no candidate could be produced, including when the
6100 /// organization has model-assisted features turned off. Suggestions
6101 /// are a convenience and nothing in the contract depends on them, so
6102 /// their absence is not an error.
6103 #[prost(message, repeated, tag="1")]
6104 pub suggestions: ::prost::alloc::vec::Vec<IndicatorSuggestion>,
6105}
6106// ─── Enums ──────────────────────────────────────────────────────────────────
6107
6108/// Lifecycle state of an objective.
6109#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6110#[repr(i32)]
6111pub enum ObjectiveState {
6112 Unspecified = 0,
6113 /// Being drafted. Not yet part of the organization's declared set and
6114 /// excluded from any analysis that reads the set as a whole.
6115 Draft = 1,
6116 /// Declared and in force.
6117 Active = 2,
6118 /// Withdrawn. Kept for history and for links already recorded against
6119 /// it, but no longer part of the declared set.
6120 Archived = 3,
6121}
6122impl ObjectiveState {
6123 /// String value of the enum field names used in the ProtoBuf definition.
6124 ///
6125 /// The values are not transformed in any way and thus are considered stable
6126 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6127 pub fn as_str_name(&self) -> &'static str {
6128 match self {
6129 Self::Unspecified => "OBJECTIVE_STATE_UNSPECIFIED",
6130 Self::Draft => "OBJECTIVE_STATE_DRAFT",
6131 Self::Active => "OBJECTIVE_STATE_ACTIVE",
6132 Self::Archived => "OBJECTIVE_STATE_ARCHIVED",
6133 }
6134 }
6135 /// Creates an enum from field names used in the ProtoBuf definition.
6136 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6137 match value {
6138 "OBJECTIVE_STATE_UNSPECIFIED" => Some(Self::Unspecified),
6139 "OBJECTIVE_STATE_DRAFT" => Some(Self::Draft),
6140 "OBJECTIVE_STATE_ACTIVE" => Some(Self::Active),
6141 "OBJECTIVE_STATE_ARCHIVED" => Some(Self::Archived),
6142 _ => None,
6143 }
6144 }
6145}
6146/// Whether the entry is a standing desired state or a time-bounded
6147/// effort. The distinction is structural, not cosmetic: analyses that
6148/// read the declared set as a whole (coverage, overlap, gaps) apply only
6149/// to standing objectives, because a time-bounded effort is expected to
6150/// end and would distort them.
6151#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6152#[repr(i32)]
6153pub enum ObjectiveKind {
6154 Unspecified = 0,
6155 /// A desired state with no end date, written as a condition rather
6156 /// than as a change or a target.
6157 Objective = 1,
6158 /// A time-bounded effort with an explicit end. May stand alone or hang
6159 /// off a standing objective.
6160 Initiative = 2,
6161}
6162impl ObjectiveKind {
6163 /// String value of the enum field names used in the ProtoBuf definition.
6164 ///
6165 /// The values are not transformed in any way and thus are considered stable
6166 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6167 pub fn as_str_name(&self) -> &'static str {
6168 match self {
6169 Self::Unspecified => "OBJECTIVE_KIND_UNSPECIFIED",
6170 Self::Objective => "OBJECTIVE_KIND_OBJECTIVE",
6171 Self::Initiative => "OBJECTIVE_KIND_INITIATIVE",
6172 }
6173 }
6174 /// Creates an enum from field names used in the ProtoBuf definition.
6175 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6176 match value {
6177 "OBJECTIVE_KIND_UNSPECIFIED" => Some(Self::Unspecified),
6178 "OBJECTIVE_KIND_OBJECTIVE" => Some(Self::Objective),
6179 "OBJECTIVE_KIND_INITIATIVE" => Some(Self::Initiative),
6180 _ => None,
6181 }
6182 }
6183}
6184/// A form problem detected in an objective's wording. Advisory only —
6185/// servers never reject a write because of one, and clients present the
6186/// finding alongside the suggested rewrite while still allowing the save.
6187#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6188#[repr(i32)]
6189pub enum ObjectiveWritingIssue {
6190 Unspecified = 0,
6191 /// Phrased as a change ("improve", "reduce", "increase") rather than
6192 /// as the state that should hold once the change has happened.
6193 ChangeVerb = 1,
6194 /// Carries a number, percentage or date inside the statement, which
6195 /// makes it a target rather than a state. Targets belong on
6196 /// indicators.
6197 EmbeddedTarget = 2,
6198 /// Phrased as a project ("launch", "roll out", "migrate"), which has
6199 /// an end and therefore describes an initiative rather than a
6200 /// standing objective.
6201 ProjectForm = 3,
6202}
6203impl ObjectiveWritingIssue {
6204 /// String value of the enum field names used in the ProtoBuf definition.
6205 ///
6206 /// The values are not transformed in any way and thus are considered stable
6207 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6208 pub fn as_str_name(&self) -> &'static str {
6209 match self {
6210 Self::Unspecified => "OBJECTIVE_WRITING_ISSUE_UNSPECIFIED",
6211 Self::ChangeVerb => "OBJECTIVE_WRITING_ISSUE_CHANGE_VERB",
6212 Self::EmbeddedTarget => "OBJECTIVE_WRITING_ISSUE_EMBEDDED_TARGET",
6213 Self::ProjectForm => "OBJECTIVE_WRITING_ISSUE_PROJECT_FORM",
6214 }
6215 }
6216 /// Creates an enum from field names used in the ProtoBuf definition.
6217 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6218 match value {
6219 "OBJECTIVE_WRITING_ISSUE_UNSPECIFIED" => Some(Self::Unspecified),
6220 "OBJECTIVE_WRITING_ISSUE_CHANGE_VERB" => Some(Self::ChangeVerb),
6221 "OBJECTIVE_WRITING_ISSUE_EMBEDDED_TARGET" => Some(Self::EmbeddedTarget),
6222 "OBJECTIVE_WRITING_ISSUE_PROJECT_FORM" => Some(Self::ProjectForm),
6223 _ => None,
6224 }
6225 }
6226}
6227/// Whether a higher or a lower reading of an indicator is the desired
6228/// direction.
6229#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6230#[repr(i32)]
6231pub enum IndicatorDirection {
6232 Unspecified = 0,
6233 HigherIsBetter = 1,
6234 LowerIsBetter = 2,
6235}
6236impl IndicatorDirection {
6237 /// String value of the enum field names used in the ProtoBuf definition.
6238 ///
6239 /// The values are not transformed in any way and thus are considered stable
6240 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6241 pub fn as_str_name(&self) -> &'static str {
6242 match self {
6243 Self::Unspecified => "INDICATOR_DIRECTION_UNSPECIFIED",
6244 Self::HigherIsBetter => "INDICATOR_DIRECTION_HIGHER_IS_BETTER",
6245 Self::LowerIsBetter => "INDICATOR_DIRECTION_LOWER_IS_BETTER",
6246 }
6247 }
6248 /// Creates an enum from field names used in the ProtoBuf definition.
6249 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6250 match value {
6251 "INDICATOR_DIRECTION_UNSPECIFIED" => Some(Self::Unspecified),
6252 "INDICATOR_DIRECTION_HIGHER_IS_BETTER" => Some(Self::HigherIsBetter),
6253 "INDICATOR_DIRECTION_LOWER_IS_BETTER" => Some(Self::LowerIsBetter),
6254 _ => None,
6255 }
6256 }
6257}
6258/// How often an indicator is expected to be read.
6259#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6260#[repr(i32)]
6261pub enum IndicatorFrequency {
6262 Unspecified = 0,
6263 Daily = 1,
6264 Weekly = 2,
6265 Monthly = 3,
6266 Quarterly = 4,
6267 Annually = 5,
6268 /// Read on demand, with no fixed cadence.
6269 AdHoc = 6,
6270}
6271impl IndicatorFrequency {
6272 /// String value of the enum field names used in the ProtoBuf definition.
6273 ///
6274 /// The values are not transformed in any way and thus are considered stable
6275 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6276 pub fn as_str_name(&self) -> &'static str {
6277 match self {
6278 Self::Unspecified => "INDICATOR_FREQUENCY_UNSPECIFIED",
6279 Self::Daily => "INDICATOR_FREQUENCY_DAILY",
6280 Self::Weekly => "INDICATOR_FREQUENCY_WEEKLY",
6281 Self::Monthly => "INDICATOR_FREQUENCY_MONTHLY",
6282 Self::Quarterly => "INDICATOR_FREQUENCY_QUARTERLY",
6283 Self::Annually => "INDICATOR_FREQUENCY_ANNUALLY",
6284 Self::AdHoc => "INDICATOR_FREQUENCY_AD_HOC",
6285 }
6286 }
6287 /// Creates an enum from field names used in the ProtoBuf definition.
6288 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6289 match value {
6290 "INDICATOR_FREQUENCY_UNSPECIFIED" => Some(Self::Unspecified),
6291 "INDICATOR_FREQUENCY_DAILY" => Some(Self::Daily),
6292 "INDICATOR_FREQUENCY_WEEKLY" => Some(Self::Weekly),
6293 "INDICATOR_FREQUENCY_MONTHLY" => Some(Self::Monthly),
6294 "INDICATOR_FREQUENCY_QUARTERLY" => Some(Self::Quarterly),
6295 "INDICATOR_FREQUENCY_ANNUALLY" => Some(Self::Annually),
6296 "INDICATOR_FREQUENCY_AD_HOC" => Some(Self::AdHoc),
6297 _ => None,
6298 }
6299 }
6300}
6301/// Where an indicator's readings come from. Each kind is an adapter over
6302/// the same contract; kinds that are not yet implemented are rejected
6303/// with UNIMPLEMENTED rather than silently accepted.
6304#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6305#[repr(i32)]
6306pub enum EvidenceSourceKind {
6307 Unspecified = 0,
6308 /// Signals produced inside the product by the audience of the message
6309 /// itself (acknowledgment, poll answer, and so on). Carries
6310 /// InAppEvidence.
6311 InApp = 1,
6312 /// A deferred follow-up message sent to someone other than the
6313 /// audience, whose answer is stored as a reading of this indicator.
6314 /// Carries VerificationCampaignEvidence.
6315 VerificationCampaign = 2,
6316 /// The organization pushes the operational fact from one of its own
6317 /// systems. Carries WebhookEvidence. Returns UNIMPLEMENTED until the
6318 /// adapter is built.
6319 Webhook = 3,
6320 /// Readings entered by hand or imported from a spreadsheet. Carries
6321 /// ManualEntryEvidence. Returns UNIMPLEMENTED until the adapter is
6322 /// built.
6323 ManualEntry = 4,
6324}
6325impl EvidenceSourceKind {
6326 /// String value of the enum field names used in the ProtoBuf definition.
6327 ///
6328 /// The values are not transformed in any way and thus are considered stable
6329 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6330 pub fn as_str_name(&self) -> &'static str {
6331 match self {
6332 Self::Unspecified => "EVIDENCE_SOURCE_KIND_UNSPECIFIED",
6333 Self::InApp => "EVIDENCE_SOURCE_KIND_IN_APP",
6334 Self::VerificationCampaign => "EVIDENCE_SOURCE_KIND_VERIFICATION_CAMPAIGN",
6335 Self::Webhook => "EVIDENCE_SOURCE_KIND_WEBHOOK",
6336 Self::ManualEntry => "EVIDENCE_SOURCE_KIND_MANUAL_ENTRY",
6337 }
6338 }
6339 /// Creates an enum from field names used in the ProtoBuf definition.
6340 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6341 match value {
6342 "EVIDENCE_SOURCE_KIND_UNSPECIFIED" => Some(Self::Unspecified),
6343 "EVIDENCE_SOURCE_KIND_IN_APP" => Some(Self::InApp),
6344 "EVIDENCE_SOURCE_KIND_VERIFICATION_CAMPAIGN" => Some(Self::VerificationCampaign),
6345 "EVIDENCE_SOURCE_KIND_WEBHOOK" => Some(Self::Webhook),
6346 "EVIDENCE_SOURCE_KIND_MANUAL_ENTRY" => Some(Self::ManualEntry),
6347 _ => None,
6348 }
6349 }
6350}
6351/// Whether an evidence source observes the whole population or a sample
6352/// of it.
6353#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6354#[repr(i32)]
6355pub enum EvidenceCoverage {
6356 Unspecified = 0,
6357 Full = 1,
6358 Sampled = 2,
6359}
6360impl EvidenceCoverage {
6361 /// String value of the enum field names used in the ProtoBuf definition.
6362 ///
6363 /// The values are not transformed in any way and thus are considered stable
6364 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6365 pub fn as_str_name(&self) -> &'static str {
6366 match self {
6367 Self::Unspecified => "EVIDENCE_COVERAGE_UNSPECIFIED",
6368 Self::Full => "EVIDENCE_COVERAGE_FULL",
6369 Self::Sampled => "EVIDENCE_COVERAGE_SAMPLED",
6370 }
6371 }
6372 /// Creates an enum from field names used in the ProtoBuf definition.
6373 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6374 match value {
6375 "EVIDENCE_COVERAGE_UNSPECIFIED" => Some(Self::Unspecified),
6376 "EVIDENCE_COVERAGE_FULL" => Some(Self::Full),
6377 "EVIDENCE_COVERAGE_SAMPLED" => Some(Self::Sampled),
6378 _ => None,
6379 }
6380 }
6381}
6382/// How the recipients of a verification message are derived from the
6383/// audience of the message being verified.
6384#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6385#[repr(i32)]
6386pub enum VerifierDerivation {
6387 Unspecified = 0,
6388 /// Each audience member's manager, deduplicated. Self-targets are
6389 /// dropped.
6390 Manager = 1,
6391}
6392impl VerifierDerivation {
6393 /// String value of the enum field names used in the ProtoBuf definition.
6394 ///
6395 /// The values are not transformed in any way and thus are considered stable
6396 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6397 pub fn as_str_name(&self) -> &'static str {
6398 match self {
6399 Self::Unspecified => "VERIFIER_DERIVATION_UNSPECIFIED",
6400 Self::Manager => "VERIFIER_DERIVATION_MANAGER",
6401 }
6402 }
6403 /// Creates an enum from field names used in the ProtoBuf definition.
6404 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6405 match value {
6406 "VERIFIER_DERIVATION_UNSPECIFIED" => Some(Self::Unspecified),
6407 "VERIFIER_DERIVATION_MANAGER" => Some(Self::Manager),
6408 _ => None,
6409 }
6410 }
6411}
6412/// Whether an indicator has ever been corroborated by evidence outside
6413/// of the declaration that created it.
6414///
6415/// Recording readings is not part of this service. An indicator becomes
6416/// verified when an IndicatorReading is stored against it, which the
6417/// platform does from campaign outcomes; no RPC defined here can move
6418/// the state, so every indicator created or updated via
6419/// ObjectivesService stays UNVERIFIED.
6420#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6421#[repr(i32)]
6422pub enum IndicatorVerificationState {
6423 Unspecified = 0,
6424 /// No corroborating reading has been recorded. This is the state of
6425 /// every newly created indicator, including one whose wording was
6426 /// suggested by a model: a suggestion is not evidence, and callers
6427 /// must not present an unverified indicator as one that is known to
6428 /// track its objective.
6429 Unverified = 1,
6430 /// At least one reading from the declared evidence source has been
6431 /// recorded against this indicator. The state says evidence exists,
6432 /// not that the evidence was favourable — an indicator corroborated by
6433 /// a negative reading is verified all the same.
6434 Verified = 2,
6435}
6436impl IndicatorVerificationState {
6437 /// String value of the enum field names used in the ProtoBuf definition.
6438 ///
6439 /// The values are not transformed in any way and thus are considered stable
6440 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6441 pub fn as_str_name(&self) -> &'static str {
6442 match self {
6443 Self::Unspecified => "INDICATOR_VERIFICATION_STATE_UNSPECIFIED",
6444 Self::Unverified => "INDICATOR_VERIFICATION_STATE_UNVERIFIED",
6445 Self::Verified => "INDICATOR_VERIFICATION_STATE_VERIFIED",
6446 }
6447 }
6448 /// Creates an enum from field names used in the ProtoBuf definition.
6449 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6450 match value {
6451 "INDICATOR_VERIFICATION_STATE_UNSPECIFIED" => Some(Self::Unspecified),
6452 "INDICATOR_VERIFICATION_STATE_UNVERIFIED" => Some(Self::Unverified),
6453 "INDICATOR_VERIFICATION_STATE_VERIFIED" => Some(Self::Verified),
6454 _ => None,
6455 }
6456 }
6457}
6458/// How a campaign came to be linked to an objective.
6459#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6460#[repr(i32)]
6461pub enum LinkOrigin {
6462 Unspecified = 0,
6463 /// Chosen explicitly by a person.
6464 Declared = 1,
6465 /// Proposed by the system from content similarity and confirmed by a
6466 /// person.
6467 Suggested = 2,
6468 /// Applied in bulk over historical campaigns when the objective set
6469 /// was first configured.
6470 Backfill = 3,
6471}
6472impl LinkOrigin {
6473 /// String value of the enum field names used in the ProtoBuf definition.
6474 ///
6475 /// The values are not transformed in any way and thus are considered stable
6476 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6477 pub fn as_str_name(&self) -> &'static str {
6478 match self {
6479 Self::Unspecified => "LINK_ORIGIN_UNSPECIFIED",
6480 Self::Declared => "LINK_ORIGIN_DECLARED",
6481 Self::Suggested => "LINK_ORIGIN_SUGGESTED",
6482 Self::Backfill => "LINK_ORIGIN_BACKFILL",
6483 }
6484 }
6485 /// Creates an enum from field names used in the ProtoBuf definition.
6486 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6487 match value {
6488 "LINK_ORIGIN_UNSPECIFIED" => Some(Self::Unspecified),
6489 "LINK_ORIGIN_DECLARED" => Some(Self::Declared),
6490 "LINK_ORIGIN_SUGGESTED" => Some(Self::Suggested),
6491 "LINK_ORIGIN_BACKFILL" => Some(Self::Backfill),
6492 _ => None,
6493 }
6494 }
6495}
6496// ─── Messages ───────────────────────────────────────────────────────────────
6497
6498/// A single non-retired pepper version. Returned by GetPeppers.
6499///
6500/// During a rotation overlap, multiple versions are returned — callers
6501/// (e.g. pidgr-integrations) compute lookup hashes under EVERY returned
6502/// version to write or match against `identifier_lookup_hash_v1` and
6503/// `identifier_lookup_hash_v2` on the reachability registry.
6504#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6505pub struct Pepper {
6506 /// Monotonically-increasing version number. Lower versions retire first.
6507 #[prost(int32, tag="1")]
6508 pub version: i32,
6509 /// Raw HMAC key material. Sensitive — callers MUST NOT log or persist
6510 /// this value to disk. In-memory caching keyed on (org_id, version) with
6511 /// a short TTL is permitted and expected.
6512 #[prost(bytes="vec", tag="2")]
6513 pub key_material: ::prost::alloc::vec::Vec<u8>,
6514}
6515/// Request to fetch the active (non-retired) peppers for one org/purpose.
6516///
6517/// Auth: internal-mTLS only. This RPC exposes raw cryptographic key material
6518/// and MUST NOT be reachable from the public ingress or from JWT-authenticated
6519/// clients. The server SHALL reject any caller whose mTLS identity is not on
6520/// the configured allowlist.
6521#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6522pub struct GetPeppersRequest {
6523 /// Organization whose peppers are requested.
6524 #[prost(string, tag="1")]
6525 pub org_id: ::prost::alloc::string::String,
6526 /// Purpose identifier scoping which key family to return. Use
6527 /// `"reachability_lookup"` for the pidgr-integrations registry lookup hash.
6528 #[prost(string, tag="2")]
6529 pub purpose: ::prost::alloc::string::String,
6530}
6531#[derive(Clone, PartialEq, ::prost::Message)]
6532pub struct GetPeppersResponse {
6533 /// All non-retired pepper versions for the (org_id, purpose) pair, in
6534 /// ascending version order. Typically exactly one entry; two during a
6535 /// rotation overlap window; zero only when no pepper has ever been
6536 /// generated for this (org, purpose).
6537 #[prost(message, repeated, tag="1")]
6538 pub peppers: ::prost::alloc::vec::Vec<Pepper>,
6539}
6540// ─── Messages ───────────────────────────────────────────────────────────────
6541
6542/// Maps an identity provider claim to a user profile field.
6543/// Used for automatic profile population when users authenticate via SSO/SAML.
6544#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6545pub struct SsoAttributeMapping {
6546 /// Claim name from the identity provider (e.g. "urn:oid:2.5.4.11", "given_name").
6547 /// Constraints: Max length 500 characters.
6548 #[prost(string, tag="1")]
6549 pub idp_claim: ::prost::alloc::string::String,
6550 /// Target UserProfile field name (e.g. "department", "first_name").
6551 /// For custom attributes, use "custom:" prefix (e.g. "custom:cost_center").
6552 /// Constraints: Max length 100 characters.
6553 #[prost(string, tag="2")]
6554 pub profile_field: ::prost::alloc::string::String,
6555}
6556/// An organization (tenant) in the Pidgr platform.
6557#[derive(Clone, PartialEq, ::prost::Message)]
6558pub struct Organization {
6559 /// Unique identifier for the organization.
6560 #[prost(string, tag="1")]
6561 pub id: ::prost::alloc::string::String,
6562 /// Organization display name.
6563 /// Constraints: Max length 200 characters.
6564 #[prost(string, tag="2")]
6565 pub name: ::prost::alloc::string::String,
6566 /// Default workflow used when campaigns don't specify one.
6567 #[prost(message, optional, tag="3")]
6568 pub default_workflow: ::core::option::Option<WorkflowDefinition>,
6569 /// Timestamp when the organization was created.
6570 #[prost(message, optional, tag="4")]
6571 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
6572 /// Industry vertical.
6573 #[prost(enumeration="Industry", tag="5")]
6574 pub industry: i32,
6575 /// Employee headcount range.
6576 #[prost(enumeration="CompanySize", tag="6")]
6577 pub company_size: i32,
6578 /// SSO identity provider claim-to-profile mappings.
6579 /// Empty when the organization does not use SSO.
6580 #[prost(message, repeated, tag="7")]
6581 pub sso_attribute_mappings: ::prost::alloc::vec::Vec<SsoAttributeMapping>,
6582 /// Default language for new users in this organization.
6583 /// Empty means no org default (users auto-detect from device/browser).
6584 /// Valid values: en, es, pt-BR, zh, ja.
6585 #[prost(string, tag="8")]
6586 pub default_locale: ::prost::alloc::string::String,
6587 /// Organization lifecycle type.
6588 #[prost(enumeration="OrgType", tag="9")]
6589 pub org_type: i32,
6590 /// Expiration time for sandbox organizations. Empty for standard orgs.
6591 #[prost(message, optional, tag="10")]
6592 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
6593 /// Data governance framework (EU, LATAM, BR, APAC, US).
6594 /// Determines legal framework, DPA template, and Bedrock endpoint routing.
6595 #[prost(string, tag="11")]
6596 pub data_governance_region: ::prost::alloc::string::String,
6597 /// AWS region for content storage (resolved from data_governance_region).
6598 /// e.g., "eu-west-1", "us-east-1".
6599 #[prost(string, tag="12")]
6600 pub data_content_region: ::prost::alloc::string::String,
6601 /// ─── ML pipeline settings ──────────────────────────────────────────────────
6602 /// Cold-start threshold: completed campaigns below this count trigger immediate
6603 /// retraining. At or above, the org is flagged for the weekly cron.
6604 /// Default 10, range 1-100.
6605 #[prost(int32, tag="13")]
6606 pub ml_retrain_cold_threshold: i32,
6607 /// Whether cancelled campaigns count toward the training counter. Default true.
6608 #[prost(bool, tag="14")]
6609 pub ml_cancelled_counts: bool,
6610 /// Monthly limit on manual retrain triggers. Default 3, range 0-10.
6611 #[prost(int32, tag="15")]
6612 pub ml_manual_limit_monthly: i32,
6613 /// Number of manual retrains used in the current month (resets monthly).
6614 #[prost(int32, tag="16")]
6615 pub ml_manual_retrains_used: i32,
6616 /// Whether the org is flagged for the next weekly cron run.
6617 #[prost(bool, tag="17")]
6618 pub ml_needs_retrain: bool,
6619 /// Campaigns completed since the last ML training run.
6620 #[prost(int32, tag="18")]
6621 pub campaigns_since_last_training: i32,
6622 /// Total campaigns completed across the organization lifetime.
6623 #[prost(int32, tag="19")]
6624 pub total_completed_campaigns: i32,
6625 /// Timestamp of the most recent successful ML training. Empty if never trained.
6626 #[prost(message, optional, tag="20")]
6627 pub last_ml_training_at: ::core::option::Option<::prost_types::Timestamp>,
6628 /// Controls whether aggregate stats (campaign recipient/ack/missed counts)
6629 /// include synthetic data. Unset = default by org type: sandbox orgs include,
6630 /// standard orgs exclude. Derived intelligence (ML, analytics, attestation
6631 /// evidence) always excludes synthetic regardless of this setting.
6632 #[prost(bool, optional, tag="21")]
6633 pub include_synthetic_in_aggregates: ::core::option::Option<bool>,
6634 /// Whether the organization has opted into provisional (rule-based,
6635 /// low-confidence) archetypes for groups that don't yet have trained
6636 /// ML archetypes. Only meaningful for ORG_TYPE_STANDARD — sandbox
6637 /// organizations are always eligible regardless of this setting.
6638 /// Default false: production analytics stay conservative.
6639 #[prost(bool, tag="22")]
6640 pub provisional_archetypes_enabled: bool,
6641}
6642/// Request to create a new organization.
6643/// JWT auth only — the authenticated caller becomes the initial admin. Additional
6644/// admins are added via CreateInviteLink after the org exists.
6645#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6646pub struct CreateOrganizationRequest {
6647 /// Name for the new organization.
6648 /// Constraints: Max length 200 characters.
6649 #[prost(string, tag="1")]
6650 pub name: ::prost::alloc::string::String,
6651 /// Industry vertical for the organization.
6652 #[prost(enumeration="Industry", tag="2")]
6653 pub industry: i32,
6654 /// Employee headcount range.
6655 #[prost(enumeration="CompanySize", tag="3")]
6656 pub company_size: i32,
6657 /// Access code required during early access.
6658 /// Format: PIDGR-XXXXXXXX (8 alphanumeric characters).
6659 #[prost(string, tag="4")]
6660 pub access_code: ::prost::alloc::string::String,
6661 /// Data governance framework. Defaults to "US" if omitted.
6662 /// Valid values: EU, LATAM, BR, APAC, US.
6663 #[prost(string, tag="5")]
6664 pub data_governance_region: ::prost::alloc::string::String,
6665 /// Optional bootstrap fixture to seed the organization with starter data.
6666 /// Empty string means the default fixture.
6667 #[prost(string, tag="6")]
6668 pub fixture_id: ::prost::alloc::string::String,
6669}
6670/// Response after creating an organization.
6671#[derive(Clone, PartialEq, ::prost::Message)]
6672pub struct CreateOrganizationResponse {
6673 /// The newly created organization.
6674 #[prost(message, optional, tag="1")]
6675 pub organization: ::core::option::Option<Organization>,
6676 /// The admin user created for the organization.
6677 #[prost(message, optional, tag="2")]
6678 pub admin_user: ::core::option::Option<User>,
6679}
6680/// Request to retrieve the organization for the authenticated user.
6681#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
6682pub struct GetOrganizationRequest {
6683}
6684/// Response containing the organization.
6685#[derive(Clone, PartialEq, ::prost::Message)]
6686pub struct GetOrganizationResponse {
6687 /// The organization the authenticated user belongs to.
6688 #[prost(message, optional, tag="1")]
6689 pub organization: ::core::option::Option<Organization>,
6690}
6691/// Request to update organization settings.
6692#[derive(Clone, PartialEq, ::prost::Message)]
6693pub struct UpdateOrganizationRequest {
6694 /// New organization name. Empty string leaves unchanged.
6695 /// Constraints: Max length 200 characters.
6696 #[prost(string, tag="1")]
6697 pub name: ::prost::alloc::string::String,
6698 /// New default workflow definition. Null leaves unchanged.
6699 #[prost(message, optional, tag="2")]
6700 pub default_workflow: ::core::option::Option<WorkflowDefinition>,
6701 /// New industry vertical. UNSPECIFIED leaves unchanged.
6702 #[prost(enumeration="Industry", tag="3")]
6703 pub industry: i32,
6704 /// New employee headcount range. UNSPECIFIED leaves unchanged.
6705 #[prost(enumeration="CompanySize", tag="4")]
6706 pub company_size: i32,
6707 /// New default language for new users. Empty string leaves unchanged.
6708 /// Valid values: en, es, pt-BR, zh, ja.
6709 #[prost(string, tag="5")]
6710 pub default_locale: ::prost::alloc::string::String,
6711 /// New ML cold-start threshold. 0 leaves unchanged, otherwise must be in \[1, 100\].
6712 #[prost(int32, tag="6")]
6713 pub ml_retrain_cold_threshold: i32,
6714 /// New ML cancelled-counts flag. Uses google.protobuf.BoolValue-style semantics
6715 /// via optional to distinguish "not provided" from "set to false".
6716 #[prost(bool, optional, tag="7")]
6717 pub ml_cancelled_counts: ::core::option::Option<bool>,
6718 /// New ML monthly manual limit. Negative leaves unchanged, otherwise must be in \[0, 10\].
6719 /// Encoded as int32 with -1 meaning "leave unchanged".
6720 #[prost(int32, tag="8")]
6721 pub ml_manual_limit_monthly: i32,
6722 /// Set the synthetic-aggregates override; unset leaves it unchanged.
6723 #[prost(bool, optional, tag="9")]
6724 pub include_synthetic_in_aggregates: ::core::option::Option<bool>,
6725 /// New provisional-archetypes opt-in for standard organizations.
6726 /// Unset leaves unchanged. Rejected for sandbox organizations, which
6727 /// are always eligible automatically.
6728 #[prost(bool, optional, tag="10")]
6729 pub provisional_archetypes_enabled: ::core::option::Option<bool>,
6730}
6731/// Response after updating the organization.
6732#[derive(Clone, PartialEq, ::prost::Message)]
6733pub struct UpdateOrganizationResponse {
6734 /// The updated organization.
6735 #[prost(message, optional, tag="1")]
6736 pub organization: ::core::option::Option<Organization>,
6737}
6738/// Request to replace all SSO attribute mappings for the organization.
6739#[derive(Clone, PartialEq, ::prost::Message)]
6740pub struct UpdateSsoAttributeMappingsRequest {
6741 /// Complete list of SSO mappings (replaces all existing mappings).
6742 #[prost(message, repeated, tag="1")]
6743 pub sso_attribute_mappings: ::prost::alloc::vec::Vec<SsoAttributeMapping>,
6744}
6745/// Response after updating SSO attribute mappings.
6746#[derive(Clone, PartialEq, ::prost::Message)]
6747pub struct UpdateSsoAttributeMappingsResponse {
6748 /// The updated organization with the new SSO mappings.
6749 #[prost(message, optional, tag="1")]
6750 pub organization: ::core::option::Option<Organization>,
6751}
6752/// Request to rotate the analytics salt and optionally increase the bucket count.
6753#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
6754pub struct RotateAnalyticsSaltRequest {
6755 /// New bucket count. Must be >= current bucket count. 0 means keep current.
6756 #[prost(int32, tag="1")]
6757 pub new_bucket_count: i32,
6758}
6759/// Response after rotating the analytics salt.
6760#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
6761pub struct RotateAnalyticsSaltResponse {
6762 /// The new bucket count after rotation.
6763 #[prost(int32, tag="1")]
6764 pub bucket_count: i32,
6765}
6766/// Request to update the analytics epsilon (differential privacy parameter).
6767#[derive(Clone, Copy, PartialEq, ::prost::Message)]
6768pub struct UpdateAnalyticsEpsilonRequest {
6769 /// New epsilon value. Must be in range \[0.5, 5.0\].
6770 #[prost(float, tag="1")]
6771 pub epsilon: f32,
6772}
6773/// Response after updating the analytics epsilon.
6774#[derive(Clone, Copy, PartialEq, ::prost::Message)]
6775pub struct UpdateAnalyticsEpsilonResponse {
6776 /// The new epsilon value.
6777 #[prost(float, tag="1")]
6778 pub epsilon: f32,
6779}
6780/// Request to create a sandbox organization for testing.
6781#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6782pub struct CreateSandboxOrganizationRequest {
6783 /// Name for the sandbox organization.
6784 /// Constraints: Max length 200 characters.
6785 #[prost(string, tag="1")]
6786 pub name: ::prost::alloc::string::String,
6787 /// Required expiration time. Max 30 days from now for interactive callers;
6788 /// API-key callers may set shorter TTLs for ephemeral test sandboxes.
6789 #[prost(message, optional, tag="2")]
6790 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
6791 /// Data governance framework. Defaults to "US" if omitted.
6792 /// Valid values: EU, LATAM, BR, APAC, US.
6793 #[prost(string, tag="3")]
6794 pub data_governance_region: ::prost::alloc::string::String,
6795 /// Optional bootstrap fixture to seed the sandbox with starter data.
6796 /// Empty string means the default fixture.
6797 /// Must match an id returned by ListSandboxFixtures.
6798 #[prost(string, tag="4")]
6799 pub fixture_id: ::prost::alloc::string::String,
6800}
6801/// Response after creating a sandbox organization.
6802#[derive(Clone, PartialEq, ::prost::Message)]
6803pub struct CreateSandboxOrganizationResponse {
6804 /// The newly created sandbox organization (org_type: SANDBOX).
6805 #[prost(message, optional, tag="1")]
6806 pub organization: ::core::option::Option<Organization>,
6807 /// The admin user created for the sandbox.
6808 #[prost(message, optional, tag="2")]
6809 pub admin_user: ::core::option::Option<User>,
6810}
6811/// Request to delete a sandbox organization. Only callable for orgs with
6812/// org_type=SANDBOX. Allowed for super admins of the sandbox or the creator.
6813#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6814pub struct DeleteSandboxOrganizationRequest {
6815 /// ID of the sandbox organization to delete.
6816 #[prost(string, tag="1")]
6817 pub org_id: ::prost::alloc::string::String,
6818}
6819/// Response after requesting deletion. Deletion runs asynchronously via
6820/// the DeleteOrgWorkflow; a success response means the workflow started.
6821#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6822pub struct DeleteSandboxOrganizationResponse {
6823 /// ID of the Temporal workflow handling the deletion.
6824 #[prost(string, tag="1")]
6825 pub workflow_id: ::prost::alloc::string::String,
6826}
6827/// A bootstrap fixture that can be applied when creating a new organization.
6828#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6829pub struct SandboxFixture {
6830 /// Stable slug for referencing this fixture (e.g. "starter", "empty",
6831 /// "fintech", "sales"). Pass it back as the fixture_id on create.
6832 #[prost(string, tag="1")]
6833 pub id: ::prost::alloc::string::String,
6834 /// Display name for admin UI (e.g. "Starter").
6835 #[prost(string, tag="2")]
6836 pub name: ::prost::alloc::string::String,
6837 /// Description shown alongside the fixture option in the UI.
6838 #[prost(string, tag="3")]
6839 pub description: ::prost::alloc::string::String,
6840 /// Exactly one fixture has is_default=true. Clients that show a simple
6841 /// "seed initial data" control select this fixture's id by default.
6842 #[prost(bool, tag="4")]
6843 pub is_default: bool,
6844}
6845/// Request to list all bootstrap fixtures available for seeding.
6846/// No parameters — catalog is the same for all callers.
6847#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
6848pub struct ListSandboxFixturesRequest {
6849}
6850/// Response containing the bootstrap fixture catalog.
6851#[derive(Clone, PartialEq, ::prost::Message)]
6852pub struct ListSandboxFixturesResponse {
6853 /// All registered fixtures, ordered by name.
6854 #[prost(message, repeated, tag="1")]
6855 pub fixtures: ::prost::alloc::vec::Vec<SandboxFixture>,
6856}
6857/// Request to list all organizations the authenticated user belongs to.
6858/// No parameters — user identity is extracted from the JWT sub claim.
6859#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
6860pub struct ListUserOrganizationsRequest {
6861}
6862/// Response containing all organizations the authenticated user belongs to.
6863#[derive(Clone, PartialEq, ::prost::Message)]
6864pub struct ListUserOrganizationsResponse {
6865 /// Organizations the user belongs to, ordered by created_at ascending.
6866 /// Excludes expired sandbox organizations.
6867 #[prost(message, repeated, tag="1")]
6868 pub organizations: ::prost::alloc::vec::Vec<Organization>,
6869}
6870/// Request to list only the sandbox organizations the authenticated user
6871/// belongs to (i.e. orgs where org_type = SANDBOX, filtered from the full
6872/// membership set). No parameters — user identity is extracted from the JWT
6873/// sub claim.
6874#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
6875pub struct ListUserSandboxesRequest {
6876}
6877/// Response containing the user's sandbox organizations.
6878#[derive(Clone, PartialEq, ::prost::Message)]
6879pub struct ListUserSandboxesResponse {
6880 /// Sandbox organizations the user belongs to, ordered by expires_at
6881 /// ascending (soonest-expiring first — matches the admin UI
6882 /// /organization/sandboxes ordering). Excludes already-expired sandboxes
6883 /// (those are pending cleanup by SandboxCleanupWorkflow).
6884 #[prost(message, repeated, tag="1")]
6885 pub sandboxes: ::prost::alloc::vec::Vec<Organization>,
6886}
6887/// A single org-level data-processing toggle with consent-trace metadata.
6888/// The metadata records who flipped the toggle last and when, so the admin
6889/// consent-trace UI can show a verifiable change trail.
6890#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6891pub struct OrgPrivacyToggle {
6892 /// Whether this category of processing is enabled for the organization.
6893 #[prost(bool, tag="1")]
6894 pub enabled: bool,
6895 /// Email of the admin who last changed this toggle.
6896 /// Empty if the toggle has never been changed from its default.
6897 #[prost(string, tag="2")]
6898 pub last_changed_by_email: ::prost::alloc::string::String,
6899 /// When this toggle was last changed.
6900 /// Empty if the toggle has never been changed from its default.
6901 #[prost(message, optional, tag="3")]
6902 pub last_changed_at: ::core::option::Option<::prost_types::Timestamp>,
6903}
6904/// Org-level data-processing settings (compliance consent surface).
6905/// Each toggle gates an entire category of processing for every user in
6906/// the organization.
6907#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6908pub struct OrgPrivacySettings {
6909 /// Gates ML archetype clustering and ACK predictions.
6910 #[prost(message, optional, tag="1")]
6911 pub ai_clustering: ::core::option::Option<OrgPrivacyToggle>,
6912 /// Gates behavioral analytics (session replay, heatmaps, dwell metrics).
6913 #[prost(message, optional, tag="2")]
6914 pub behavioral_analytics: ::core::option::Option<OrgPrivacyToggle>,
6915 /// Gates third-party notification channel dispatch (email, Slack, SMS, …).
6916 #[prost(message, optional, tag="3")]
6917 pub third_party_channels: ::core::option::Option<OrgPrivacyToggle>,
6918}
6919/// Request to retrieve the org-level privacy settings.
6920/// The organization is extracted from the JWT.
6921#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
6922pub struct GetOrgPrivacySettingsRequest {
6923}
6924/// Response containing the org-level privacy settings with consent-trace
6925/// metadata for each toggle.
6926#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6927pub struct GetOrgPrivacySettingsResponse {
6928 /// The organization's current privacy settings.
6929 #[prost(message, optional, tag="1")]
6930 pub settings: ::core::option::Option<OrgPrivacySettings>,
6931}
6932/// Request to update org-level privacy settings. Only the provided fields
6933/// are changed; unset fields leave the corresponding toggle unchanged.
6934#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
6935pub struct UpdateOrgPrivacySettingsRequest {
6936 /// Enable or disable ML archetype clustering and ACK predictions.
6937 /// Unset leaves unchanged.
6938 #[prost(bool, optional, tag="1")]
6939 pub ai_clustering_enabled: ::core::option::Option<bool>,
6940 /// Enable or disable behavioral analytics. Unset leaves unchanged.
6941 #[prost(bool, optional, tag="2")]
6942 pub behavioral_analytics_enabled: ::core::option::Option<bool>,
6943 /// Enable or disable third-party notification channels.
6944 /// Unset leaves unchanged.
6945 #[prost(bool, optional, tag="3")]
6946 pub third_party_channels_enabled: ::core::option::Option<bool>,
6947}
6948/// Response after updating org-level privacy settings.
6949#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
6950pub struct UpdateOrgPrivacySettingsResponse {
6951 /// The organization's privacy settings after the update, with refreshed
6952 /// consent-trace metadata.
6953 #[prost(message, optional, tag="1")]
6954 pub settings: ::core::option::Option<OrgPrivacySettings>,
6955}
6956// ─── Enums ───────────────────────────────────────────────────────────────────
6957
6958/// Industry vertical for an organization.
6959#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
6960#[repr(i32)]
6961pub enum Industry {
6962 Unspecified = 0,
6963 Technology = 1,
6964 Finance = 2,
6965 Healthcare = 3,
6966 Education = 4,
6967 Retail = 5,
6968 Manufacturing = 6,
6969 Media = 7,
6970 Other = 8,
6971}
6972impl Industry {
6973 /// String value of the enum field names used in the ProtoBuf definition.
6974 ///
6975 /// The values are not transformed in any way and thus are considered stable
6976 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
6977 pub fn as_str_name(&self) -> &'static str {
6978 match self {
6979 Self::Unspecified => "INDUSTRY_UNSPECIFIED",
6980 Self::Technology => "INDUSTRY_TECHNOLOGY",
6981 Self::Finance => "INDUSTRY_FINANCE",
6982 Self::Healthcare => "INDUSTRY_HEALTHCARE",
6983 Self::Education => "INDUSTRY_EDUCATION",
6984 Self::Retail => "INDUSTRY_RETAIL",
6985 Self::Manufacturing => "INDUSTRY_MANUFACTURING",
6986 Self::Media => "INDUSTRY_MEDIA",
6987 Self::Other => "INDUSTRY_OTHER",
6988 }
6989 }
6990 /// Creates an enum from field names used in the ProtoBuf definition.
6991 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
6992 match value {
6993 "INDUSTRY_UNSPECIFIED" => Some(Self::Unspecified),
6994 "INDUSTRY_TECHNOLOGY" => Some(Self::Technology),
6995 "INDUSTRY_FINANCE" => Some(Self::Finance),
6996 "INDUSTRY_HEALTHCARE" => Some(Self::Healthcare),
6997 "INDUSTRY_EDUCATION" => Some(Self::Education),
6998 "INDUSTRY_RETAIL" => Some(Self::Retail),
6999 "INDUSTRY_MANUFACTURING" => Some(Self::Manufacturing),
7000 "INDUSTRY_MEDIA" => Some(Self::Media),
7001 "INDUSTRY_OTHER" => Some(Self::Other),
7002 _ => None,
7003 }
7004 }
7005}
7006/// Employee headcount range for an organization.
7007#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
7008#[repr(i32)]
7009pub enum CompanySize {
7010 Unspecified = 0,
7011 CompanySize1200 = 1,
7012 CompanySize200500 = 2,
7013 CompanySize5001000 = 3,
7014 CompanySize10005000 = 4,
7015 CompanySize5000Plus = 5,
7016}
7017impl CompanySize {
7018 /// String value of the enum field names used in the ProtoBuf definition.
7019 ///
7020 /// The values are not transformed in any way and thus are considered stable
7021 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
7022 pub fn as_str_name(&self) -> &'static str {
7023 match self {
7024 Self::Unspecified => "COMPANY_SIZE_UNSPECIFIED",
7025 Self::CompanySize1200 => "COMPANY_SIZE_1_200",
7026 Self::CompanySize200500 => "COMPANY_SIZE_200_500",
7027 Self::CompanySize5001000 => "COMPANY_SIZE_500_1000",
7028 Self::CompanySize10005000 => "COMPANY_SIZE_1000_5000",
7029 Self::CompanySize5000Plus => "COMPANY_SIZE_5000_PLUS",
7030 }
7031 }
7032 /// Creates an enum from field names used in the ProtoBuf definition.
7033 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
7034 match value {
7035 "COMPANY_SIZE_UNSPECIFIED" => Some(Self::Unspecified),
7036 "COMPANY_SIZE_1_200" => Some(Self::CompanySize1200),
7037 "COMPANY_SIZE_200_500" => Some(Self::CompanySize200500),
7038 "COMPANY_SIZE_500_1000" => Some(Self::CompanySize5001000),
7039 "COMPANY_SIZE_1000_5000" => Some(Self::CompanySize10005000),
7040 "COMPANY_SIZE_5000_PLUS" => Some(Self::CompanySize5000Plus),
7041 _ => None,
7042 }
7043 }
7044}
7045/// Classification of an organization's lifecycle type.
7046#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
7047#[repr(i32)]
7048pub enum OrgType {
7049 Unspecified = 0,
7050 Standard = 1,
7051 Sandbox = 2,
7052 /// Reserved for platform operations. At most one per deployment, seeded
7053 /// by migration. Cannot be created via CreateOrganization.
7054 Staff = 3,
7055}
7056impl OrgType {
7057 /// String value of the enum field names used in the ProtoBuf definition.
7058 ///
7059 /// The values are not transformed in any way and thus are considered stable
7060 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
7061 pub fn as_str_name(&self) -> &'static str {
7062 match self {
7063 Self::Unspecified => "ORG_TYPE_UNSPECIFIED",
7064 Self::Standard => "ORG_TYPE_STANDARD",
7065 Self::Sandbox => "ORG_TYPE_SANDBOX",
7066 Self::Staff => "ORG_TYPE_STAFF",
7067 }
7068 }
7069 /// Creates an enum from field names used in the ProtoBuf definition.
7070 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
7071 match value {
7072 "ORG_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
7073 "ORG_TYPE_STANDARD" => Some(Self::Standard),
7074 "ORG_TYPE_SANDBOX" => Some(Self::Sandbox),
7075 "ORG_TYPE_STAFF" => Some(Self::Staff),
7076 _ => None,
7077 }
7078 }
7079}
7080// ─── Messages ───────────────────────────────────────────────────────────────
7081
7082/// Per-user rendering context containing variable substitutions.
7083#[derive(Clone, PartialEq, ::prost::Message)]
7084pub struct UserRenderContext {
7085 /// ID of the user being rendered for.
7086 #[prost(string, tag="1")]
7087 pub user_id: ::prost::alloc::string::String,
7088 /// Variable name-value pairs to substitute into the template.
7089 /// Constraints: Max 100 entries. Key max length 100 characters, value max length 10000 characters.
7090 #[prost(map="string, string", tag="2")]
7091 pub variables: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>,
7092}
7093/// Request to render a template for a batch of users.
7094#[derive(Clone, PartialEq, ::prost::Message)]
7095pub struct RenderBatchRequest {
7096 /// ID of the template to render.
7097 #[prost(string, tag="1")]
7098 pub template_id: ::prost::alloc::string::String,
7099 /// Version of the template to render.
7100 #[prost(int32, tag="2")]
7101 pub version: i32,
7102 /// Per-user rendering contexts with variable substitutions.
7103 /// Constraints: Max 10000 users per batch.
7104 #[prost(message, repeated, tag="3")]
7105 pub users: ::prost::alloc::vec::Vec<UserRenderContext>,
7106}
7107/// Streamed response for each user's rendered message.
7108/// One response is emitted per user in the batch.
7109#[derive(Clone, PartialEq, ::prost::Message)]
7110pub struct RenderBatchResponse {
7111 /// ID of the user this result is for.
7112 #[prost(string, tag="1")]
7113 pub user_id: ::prost::alloc::string::String,
7114 /// The rendered message (set on success).
7115 #[prost(message, optional, tag="2")]
7116 pub message: ::core::option::Option<Message>,
7117 /// Error message if rendering failed for this user (empty on success).
7118 #[prost(string, tag="3")]
7119 pub error: ::prost::alloc::string::String,
7120}
7121// ─── Messages ───────────────────────────────────────────────────────────────
7122
7123/// A session recording summary from the analytics provider.
7124/// Anonymous: no user identifiers are included.
7125#[derive(Clone, PartialEq, ::prost::Message)]
7126pub struct SessionRecording {
7127 /// Recording ID from the analytics provider.
7128 #[prost(string, tag="1")]
7129 pub id: ::prost::alloc::string::String,
7130 /// Timestamp when the recording started.
7131 #[prost(message, optional, tag="2")]
7132 pub start_time: ::core::option::Option<::prost_types::Timestamp>,
7133 /// Timestamp when the recording ended.
7134 #[prost(message, optional, tag="3")]
7135 pub end_time: ::core::option::Option<::prost_types::Timestamp>,
7136 /// Duration of the recording in seconds.
7137 #[prost(int32, tag="4")]
7138 pub duration_seconds: i32,
7139 /// Activity score (0.0–1.0).
7140 #[prost(float, tag="5")]
7141 pub activity_score: f32,
7142}
7143/// Request to list session recordings.
7144#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7145pub struct ListSessionRecordingsRequest {
7146 /// Optional: filter recordings by campaign ID (mapped to analytics property filter).
7147 /// Constraints: UUID format (36 characters).
7148 #[prost(string, tag="1")]
7149 pub campaign_id: ::prost::alloc::string::String,
7150 /// Optional: start of the time range filter (inclusive).
7151 #[prost(message, optional, tag="2")]
7152 pub date_from: ::core::option::Option<::prost_types::Timestamp>,
7153 /// Optional: end of the time range filter (inclusive).
7154 #[prost(message, optional, tag="3")]
7155 pub date_to: ::core::option::Option<::prost_types::Timestamp>,
7156 /// Pagination parameters.
7157 #[prost(message, optional, tag="4")]
7158 pub pagination: ::core::option::Option<Pagination>,
7159}
7160/// Response containing a page of session recordings.
7161#[derive(Clone, PartialEq, ::prost::Message)]
7162pub struct ListSessionRecordingsResponse {
7163 /// List of session recordings in this page.
7164 #[prost(message, repeated, tag="1")]
7165 pub recordings: ::prost::alloc::vec::Vec<SessionRecording>,
7166 /// Pagination metadata for fetching subsequent pages.
7167 #[prost(message, optional, tag="2")]
7168 pub pagination_meta: ::core::option::Option<PaginationMeta>,
7169}
7170/// Request to fetch rrweb snapshot events for a recording.
7171#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7172pub struct GetSessionSnapshotsRequest {
7173 /// Recording ID from the analytics provider.
7174 /// Constraints: Max length 200 characters.
7175 #[prost(string, tag="1")]
7176 pub recording_id: ::prost::alloc::string::String,
7177}
7178/// Response containing rrweb snapshot events.
7179#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7180pub struct GetSessionSnapshotsResponse {
7181 /// JSON-encoded array of rrweb eventWithTime objects.
7182 /// Clients parse this JSON to feed into rrweb-player.
7183 #[prost(string, tag="1")]
7184 pub snapshot_data: ::prost::alloc::string::String,
7185}
7186// ─── Messages ───────────────────────────────────────────────────────────────
7187
7188/// Request to list all roles in the caller's organization.
7189#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
7190pub struct ListRolesRequest {
7191}
7192/// Response containing the organization's roles.
7193#[derive(Clone, PartialEq, ::prost::Message)]
7194pub struct ListRolesResponse {
7195 /// All roles in the organization, including their permission sets.
7196 #[prost(message, repeated, tag="1")]
7197 pub roles: ::prost::alloc::vec::Vec<Role>,
7198}
7199/// Request to create a new role in the caller's organization.
7200#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7201pub struct CreateRoleRequest {
7202 /// Display name for the role (e.g. "Team Lead"). Required.
7203 /// A slug is auto-generated from the name.
7204 #[prost(string, tag="1")]
7205 pub name: ::prost::alloc::string::String,
7206 /// Initial permission set for the role.
7207 /// PERMISSION_UNSPECIFIED values are rejected.
7208 #[prost(enumeration="Permission", repeated, tag="2")]
7209 pub permissions: ::prost::alloc::vec::Vec<i32>,
7210}
7211/// Response after creating a role.
7212#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7213pub struct CreateRoleResponse {
7214 /// The newly created role with its generated slug and permission set.
7215 #[prost(message, optional, tag="1")]
7216 pub role: ::core::option::Option<Role>,
7217}
7218/// Request to update a role's name and/or permissions.
7219#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7220pub struct UpdateRoleRequest {
7221 /// ID of the role to update. Required.
7222 #[prost(string, tag="1")]
7223 pub role_id: ::prost::alloc::string::String,
7224 /// New display name. If empty, the name is not changed.
7225 #[prost(string, tag="2")]
7226 pub name: ::prost::alloc::string::String,
7227 /// New permission set (replaces existing permissions entirely).
7228 /// If empty, permissions are not changed.
7229 /// PERMISSION_UNSPECIFIED values are rejected.
7230 #[prost(enumeration="Permission", repeated, tag="3")]
7231 pub permissions: ::prost::alloc::vec::Vec<i32>,
7232}
7233/// Response after updating a role.
7234#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7235pub struct UpdateRoleResponse {
7236 /// The updated role.
7237 #[prost(message, optional, tag="1")]
7238 pub role: ::core::option::Option<Role>,
7239}
7240/// Request to delete a role.
7241#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7242pub struct DeleteRoleRequest {
7243 /// ID of the role to delete. Required.
7244 #[prost(string, tag="1")]
7245 pub role_id: ::prost::alloc::string::String,
7246}
7247/// Response after deleting a role.
7248#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
7249pub struct DeleteRoleResponse {
7250}
7251// ─── Messages ───────────────────────────────────────────────────────────────
7252
7253/// Custom SAML attribute name overrides for identity providers that use
7254/// non-standard attribute names. When provided, these override the
7255/// auto-detected values from the metadata URL host.
7256#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7257pub struct SamlAttributeNames {
7258 /// SAML attribute name for the user's email address.
7259 #[prost(string, tag="1")]
7260 pub email: ::prost::alloc::string::String,
7261 /// SAML attribute name for the user's first name.
7262 #[prost(string, tag="2")]
7263 pub given_name: ::prost::alloc::string::String,
7264 /// SAML attribute name for the user's last name.
7265 #[prost(string, tag="3")]
7266 pub family_name: ::prost::alloc::string::String,
7267}
7268/// An SSO identity provider configured for an organization.
7269#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7270pub struct SsoProvider {
7271 /// Unique identifier for the provider.
7272 #[prost(string, tag="1")]
7273 pub id: ::prost::alloc::string::String,
7274 /// Email domain that triggers this SSO provider (e.g. "acme.com").
7275 /// Constraints: Max length 253 characters (RFC 1035).
7276 #[prost(string, tag="2")]
7277 pub domain: ::prost::alloc::string::String,
7278 /// Type of identity provider.
7279 #[prost(enumeration="SsoProviderType", tag="3")]
7280 pub r#type: i32,
7281 /// SAML metadata URL or OIDC discovery URL.
7282 /// Constraints: Max length 2048 characters. HTTPS required.
7283 #[prost(string, tag="4")]
7284 pub metadata_url: ::prost::alloc::string::String,
7285 /// Name of the identity provider (used for signInWithRedirect).
7286 /// Set by the API when the IdP is created.
7287 #[prost(string, tag="5")]
7288 pub idp_provider_name: ::prost::alloc::string::String,
7289 /// Timestamp when the provider was created.
7290 #[prost(message, optional, tag="6")]
7291 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
7292 /// Timestamp when the provider was last updated.
7293 #[prost(message, optional, tag="7")]
7294 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
7295 /// Optional custom SAML attribute name overrides.
7296 #[prost(message, optional, tag="8")]
7297 pub attribute_mapping: ::core::option::Option<SamlAttributeNames>,
7298}
7299/// Request to check if an email domain has SSO configured.
7300/// This RPC is pre-authentication — no JWT required.
7301#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7302pub struct CheckSsoByDomainRequest {
7303 /// Email address to check. The domain part is extracted.
7304 /// Constraints: Max length 254 characters (RFC 5321).
7305 #[prost(string, tag="1")]
7306 pub email: ::prost::alloc::string::String,
7307}
7308/// Response for SSO domain check.
7309#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7310pub struct CheckSsoByDomainResponse {
7311 /// Whether SSO is enabled for the email's domain.
7312 #[prost(bool, tag="1")]
7313 pub sso_enabled: bool,
7314 /// Identity provider name for signInWithRedirect.
7315 /// Empty if sso_enabled is false.
7316 #[prost(string, tag="2")]
7317 pub provider_name: ::prost::alloc::string::String,
7318}
7319/// Request to create an SSO provider for the organization.
7320#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7321pub struct CreateSsoProviderRequest {
7322 /// Email domain to associate (e.g. "acme.com").
7323 /// Constraints: Max length 253 characters (RFC 1035).
7324 #[prost(string, tag="1")]
7325 pub domain: ::prost::alloc::string::String,
7326 /// Type of identity provider.
7327 #[prost(enumeration="SsoProviderType", tag="2")]
7328 pub r#type: i32,
7329 /// SAML metadata URL or OIDC discovery URL.
7330 /// Constraints: Max length 2048 characters. HTTPS required.
7331 #[prost(string, tag="3")]
7332 pub metadata_url: ::prost::alloc::string::String,
7333 /// Optional custom SAML attribute name overrides.
7334 /// When omitted, attribute names are auto-detected from the metadata URL.
7335 #[prost(message, optional, tag="4")]
7336 pub attribute_mapping: ::core::option::Option<SamlAttributeNames>,
7337}
7338/// Response after creating an SSO provider.
7339#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7340pub struct CreateSsoProviderResponse {
7341 /// The newly created SSO provider.
7342 #[prost(message, optional, tag="1")]
7343 pub provider: ::core::option::Option<SsoProvider>,
7344}
7345/// Request to get the SSO provider for the organization.
7346/// Returns the provider if one is configured, or empty if not.
7347#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
7348pub struct GetSsoProviderRequest {
7349}
7350/// Response containing the organization's SSO provider.
7351#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7352pub struct GetSsoProviderResponse {
7353 /// The organization's SSO provider, or null if not configured.
7354 #[prost(message, optional, tag="1")]
7355 pub provider: ::core::option::Option<SsoProvider>,
7356}
7357/// Request to delete the organization's SSO provider.
7358#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7359pub struct DeleteSsoProviderRequest {
7360 /// ID of the provider to delete.
7361 #[prost(string, tag="1")]
7362 pub provider_id: ::prost::alloc::string::String,
7363}
7364/// Response after deleting an SSO provider.
7365#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
7366pub struct DeleteSsoProviderResponse {
7367}
7368// ─── Enums ──────────────────────────────────────────────────────────────────
7369
7370/// Type of SSO identity provider.
7371#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
7372#[repr(i32)]
7373pub enum SsoProviderType {
7374 /// Default value; not a valid type.
7375 Unspecified = 0,
7376 /// SAML 2.0 identity provider (e.g. Okta, Azure AD).
7377 Saml = 1,
7378 /// OpenID Connect identity provider (e.g. Google Workspace, Auth0).
7379 Oidc = 2,
7380}
7381impl SsoProviderType {
7382 /// String value of the enum field names used in the ProtoBuf definition.
7383 ///
7384 /// The values are not transformed in any way and thus are considered stable
7385 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
7386 pub fn as_str_name(&self) -> &'static str {
7387 match self {
7388 Self::Unspecified => "SSO_PROVIDER_TYPE_UNSPECIFIED",
7389 Self::Saml => "SSO_PROVIDER_TYPE_SAML",
7390 Self::Oidc => "SSO_PROVIDER_TYPE_OIDC",
7391 }
7392 }
7393 /// Creates an enum from field names used in the ProtoBuf definition.
7394 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
7395 match value {
7396 "SSO_PROVIDER_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
7397 "SSO_PROVIDER_TYPE_SAML" => Some(Self::Saml),
7398 "SSO_PROVIDER_TYPE_OIDC" => Some(Self::Oidc),
7399 _ => None,
7400 }
7401 }
7402}
7403// ─── Messages ───────────────────────────────────────────────────────────────
7404
7405/// An organizational unit within an organization (e.g. department, division).
7406/// Teams represent the organizational structure and can serve as sender identity
7407/// in campaigns.
7408#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7409pub struct Team {
7410 /// Unique identifier for the team.
7411 #[prost(string, tag="1")]
7412 pub id: ::prost::alloc::string::String,
7413 /// Human-readable display name (unique within the organization).
7414 /// Constraints: Max length 200 characters.
7415 #[prost(string, tag="2")]
7416 pub name: ::prost::alloc::string::String,
7417 /// Optional description of the team's purpose.
7418 /// Constraints: Max length 1000 characters.
7419 #[prost(string, tag="3")]
7420 pub description: ::prost::alloc::string::String,
7421 /// Number of users currently in the team.
7422 #[prost(int32, tag="4")]
7423 pub member_count: i32,
7424 /// Timestamp when the team was created.
7425 #[prost(message, optional, tag="5")]
7426 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
7427 /// Timestamp when the team was last updated.
7428 #[prost(message, optional, tag="6")]
7429 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
7430 /// Whether this is the organization's default team (cannot be deleted or renamed).
7431 #[prost(bool, tag="7")]
7432 pub is_default: bool,
7433 /// ID of the user who created this team. Empty for system-seeded defaults.
7434 #[prost(string, tag="8")]
7435 pub created_by: ::prost::alloc::string::String,
7436}
7437/// Request to create a new team.
7438#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7439pub struct CreateTeamRequest {
7440 /// Display name for the team. Required.
7441 /// Constraints: Max length 200 characters.
7442 #[prost(string, tag="1")]
7443 pub name: ::prost::alloc::string::String,
7444 /// Optional description.
7445 /// Constraints: Max length 1000 characters.
7446 #[prost(string, tag="2")]
7447 pub description: ::prost::alloc::string::String,
7448}
7449/// Response after creating a team.
7450#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7451pub struct CreateTeamResponse {
7452 /// The newly created team.
7453 #[prost(message, optional, tag="1")]
7454 pub team: ::core::option::Option<Team>,
7455}
7456/// Request to retrieve a team by ID.
7457#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7458pub struct GetTeamRequest {
7459 /// ID of the team to retrieve. Required.
7460 #[prost(string, tag="1")]
7461 pub team_id: ::prost::alloc::string::String,
7462}
7463/// Response containing the requested team.
7464#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7465pub struct GetTeamResponse {
7466 /// The requested team.
7467 #[prost(message, optional, tag="1")]
7468 pub team: ::core::option::Option<Team>,
7469}
7470/// Request to list teams in the organization with pagination.
7471#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7472pub struct ListTeamsRequest {
7473 /// Pagination parameters.
7474 #[prost(message, optional, tag="1")]
7475 pub pagination: ::core::option::Option<Pagination>,
7476}
7477/// Response containing a page of teams.
7478#[derive(Clone, PartialEq, ::prost::Message)]
7479pub struct ListTeamsResponse {
7480 /// Teams in this page.
7481 #[prost(message, repeated, tag="1")]
7482 pub teams: ::prost::alloc::vec::Vec<Team>,
7483 /// Pagination metadata for fetching subsequent pages.
7484 #[prost(message, optional, tag="2")]
7485 pub pagination_meta: ::core::option::Option<PaginationMeta>,
7486}
7487/// Request to update a team's name and/or description.
7488#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7489pub struct UpdateTeamRequest {
7490 /// ID of the team to update. Required.
7491 #[prost(string, tag="1")]
7492 pub team_id: ::prost::alloc::string::String,
7493 /// New display name. If empty, the name is not changed.
7494 /// Default teams cannot be renamed.
7495 /// Constraints: Max length 200 characters.
7496 #[prost(string, tag="2")]
7497 pub name: ::prost::alloc::string::String,
7498 /// New description. If empty, the description is not changed.
7499 /// Constraints: Max length 1000 characters.
7500 #[prost(string, tag="3")]
7501 pub description: ::prost::alloc::string::String,
7502}
7503/// Response after updating a team.
7504#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7505pub struct UpdateTeamResponse {
7506 /// The updated team.
7507 #[prost(message, optional, tag="1")]
7508 pub team: ::core::option::Option<Team>,
7509}
7510/// Request to delete a team.
7511#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7512pub struct DeleteTeamRequest {
7513 /// ID of the team to delete. Required.
7514 /// Default teams cannot be deleted.
7515 #[prost(string, tag="1")]
7516 pub team_id: ::prost::alloc::string::String,
7517}
7518/// Response after deleting a team.
7519#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
7520pub struct DeleteTeamResponse {
7521}
7522/// Request to add users to a team.
7523#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7524pub struct AddTeamMembersRequest {
7525 /// ID of the team to add members to. Required.
7526 #[prost(string, tag="1")]
7527 pub team_id: ::prost::alloc::string::String,
7528 /// IDs of users to add. Must belong to the same organization.
7529 /// Adding an existing member is a no-op (idempotent).
7530 /// Constraints: Max 100 user IDs per request.
7531 #[prost(string, repeated, tag="2")]
7532 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
7533}
7534/// Response after adding team members.
7535#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7536pub struct AddTeamMembersResponse {
7537 /// The team with updated member_count.
7538 #[prost(message, optional, tag="1")]
7539 pub team: ::core::option::Option<Team>,
7540}
7541/// Request to remove users from a team.
7542#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7543pub struct RemoveTeamMembersRequest {
7544 /// ID of the team to remove members from. Required.
7545 #[prost(string, tag="1")]
7546 pub team_id: ::prost::alloc::string::String,
7547 /// IDs of users to remove. Removing a non-member is a no-op (idempotent).
7548 /// Constraints: Max 100 user IDs per request.
7549 #[prost(string, repeated, tag="2")]
7550 pub user_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
7551}
7552/// Response after removing team members.
7553#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7554pub struct RemoveTeamMembersResponse {
7555 /// The team with updated member_count.
7556 #[prost(message, optional, tag="1")]
7557 pub team: ::core::option::Option<Team>,
7558}
7559/// Request to list members of a team with pagination.
7560#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7561pub struct ListTeamMembersRequest {
7562 /// ID of the team whose members to list. Required.
7563 #[prost(string, tag="1")]
7564 pub team_id: ::prost::alloc::string::String,
7565 /// Pagination parameters.
7566 #[prost(message, optional, tag="2")]
7567 pub pagination: ::core::option::Option<Pagination>,
7568}
7569/// Response containing a page of team members.
7570#[derive(Clone, PartialEq, ::prost::Message)]
7571pub struct ListTeamMembersResponse {
7572 /// Users in this page.
7573 #[prost(message, repeated, tag="1")]
7574 pub users: ::prost::alloc::vec::Vec<User>,
7575 /// Pagination metadata for fetching subsequent pages.
7576 #[prost(message, optional, tag="2")]
7577 pub pagination_meta: ::core::option::Option<PaginationMeta>,
7578}
7579// ─── Messages ───────────────────────────────────────────────────────────────
7580
7581/// A variable placeholder within a template that gets substituted during rendering.
7582#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7583pub struct TemplateVariable {
7584 /// Variable name used in the template body (e.g. "employee_name").
7585 /// Constraints: Max length 100 characters.
7586 #[prost(string, tag="1")]
7587 pub name: ::prost::alloc::string::String,
7588 /// Human-readable description of what this variable represents.
7589 /// Constraints: Max length 500 characters.
7590 #[prost(string, tag="2")]
7591 pub description: ::prost::alloc::string::String,
7592 /// Whether this variable must be provided during rendering.
7593 #[prost(bool, tag="3")]
7594 pub required: bool,
7595 /// Where this variable's value comes from (profile attribute or campaign config).
7596 #[prost(enumeration="TemplateVariableSource", tag="4")]
7597 pub source: i32,
7598 /// Fallback value used when the source does not provide a value.
7599 /// Constraints: Max length 1000 characters.
7600 #[prost(string, tag="5")]
7601 pub default_value: ::prost::alloc::string::String,
7602 /// When true, this variable's rendered value is masked in session replay
7603 /// and heatmap screenshots. Org admin controls per variable.
7604 #[prost(bool, tag="6")]
7605 pub pii: bool,
7606}
7607/// A versioned message template with variable placeholders.
7608/// Templates are append-only — updates create new versions.
7609#[derive(Clone, PartialEq, ::prost::Message)]
7610pub struct Template {
7611 /// Unique identifier for the template.
7612 #[prost(string, tag="1")]
7613 pub id: ::prost::alloc::string::String,
7614 /// Human-readable template name (admin-facing label).
7615 /// Constraints: Max length 200 characters.
7616 #[prost(string, tag="2")]
7617 pub name: ::prost::alloc::string::String,
7618 /// Template body with {{variable}} placeholders for substitution.
7619 /// Constraints: Max length 50000 characters.
7620 #[prost(string, tag="3")]
7621 pub body: ::prost::alloc::string::String,
7622 /// Variables that can be substituted into the template body.
7623 #[prost(message, repeated, tag="4")]
7624 pub variables: ::prost::alloc::vec::Vec<TemplateVariable>,
7625 /// Version number (auto-incremented on each update).
7626 #[prost(int32, tag="5")]
7627 pub version: i32,
7628 /// Timestamp when this version was created.
7629 #[prost(message, optional, tag="6")]
7630 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
7631 /// Timestamp of the most recent update (same as created_at for the latest version).
7632 #[prost(message, optional, tag="7")]
7633 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
7634 /// User-facing title shown as the message subject to recipients.
7635 /// Serves as the default title; campaigns can override it.
7636 /// Constraints: Max length 200 characters.
7637 #[prost(string, tag="8")]
7638 pub title: ::prost::alloc::string::String,
7639 /// Content format of this template (markdown, rich, HTML).
7640 /// UNSPECIFIED is treated as MARKDOWN for backward compatibility.
7641 #[prost(enumeration="TemplateType", tag="9")]
7642 pub r#type: i32,
7643 /// Language of the template body content (e.g., "en", "es", "ja").
7644 /// Defaults to the org's default_locale, falling back to "en".
7645 /// Translations are created as locale variants of this source.
7646 #[prost(string, tag="10")]
7647 pub source_locale: ::prost::alloc::string::String,
7648}
7649/// A locale-specific translation of a template's title and body.
7650/// Translations are created per template version and go through a review workflow.
7651#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7652pub struct TemplateTranslation {
7653 /// Unique identifier for this translation.
7654 #[prost(string, tag="1")]
7655 pub id: ::prost::alloc::string::String,
7656 /// ID of the source template.
7657 #[prost(string, tag="2")]
7658 pub template_id: ::prost::alloc::string::String,
7659 /// Version of the source template this translation is for.
7660 #[prost(int32, tag="3")]
7661 pub version: i32,
7662 /// Target locale (e.g., "es", "pt-BR", "zh", "ja").
7663 #[prost(string, tag="4")]
7664 pub locale: ::prost::alloc::string::String,
7665 /// Translated title.
7666 /// Constraints: Max length 200 characters.
7667 #[prost(string, tag="5")]
7668 pub title: ::prost::alloc::string::String,
7669 /// Translated body content with {{variable}} placeholders preserved.
7670 /// Constraints: Max length 50000 characters.
7671 #[prost(string, tag="6")]
7672 pub body: ::prost::alloc::string::String,
7673 /// Current review status.
7674 #[prost(enumeration="TranslationStatus", tag="7")]
7675 pub status: i32,
7676 /// Who created this translation ("ai:bedrock", "ai:deepl", or user UUID).
7677 #[prost(string, tag="8")]
7678 pub translated_by: ::prost::alloc::string::String,
7679 /// User who approved the translation. Empty until approved.
7680 #[prost(string, tag="9")]
7681 pub reviewed_by: ::prost::alloc::string::String,
7682 /// When the translation was approved.
7683 #[prost(message, optional, tag="10")]
7684 pub reviewed_at: ::core::option::Option<::prost_types::Timestamp>,
7685 /// When the translation was created.
7686 #[prost(message, optional, tag="11")]
7687 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
7688}
7689/// Request to create a new template.
7690#[derive(Clone, PartialEq, ::prost::Message)]
7691pub struct CreateTemplateRequest {
7692 /// Human-readable template name (admin-facing label).
7693 /// Constraints: Max length 200 characters.
7694 #[prost(string, tag="1")]
7695 pub name: ::prost::alloc::string::String,
7696 /// Template body with {{variable}} placeholders.
7697 /// Constraints: Max length 50000 characters.
7698 #[prost(string, tag="2")]
7699 pub body: ::prost::alloc::string::String,
7700 /// Variables available for substitution in the body.
7701 #[prost(message, repeated, tag="3")]
7702 pub variables: ::prost::alloc::vec::Vec<TemplateVariable>,
7703 /// User-facing title shown as the message subject to recipients.
7704 /// Constraints: Max length 200 characters.
7705 #[prost(string, tag="4")]
7706 pub title: ::prost::alloc::string::String,
7707 /// Content format of the template. Defaults to MARKDOWN if unspecified.
7708 #[prost(enumeration="TemplateType", tag="5")]
7709 pub r#type: i32,
7710 /// Language of the template body content. Defaults to org's default_locale.
7711 /// Valid values: en, es, pt-BR, zh, ja.
7712 #[prost(string, tag="6")]
7713 pub source_locale: ::prost::alloc::string::String,
7714}
7715/// Response after creating a template.
7716#[derive(Clone, PartialEq, ::prost::Message)]
7717pub struct CreateTemplateResponse {
7718 /// The newly created template (version 1).
7719 #[prost(message, optional, tag="1")]
7720 pub template: ::core::option::Option<Template>,
7721}
7722/// Request to update a template, creating a new version.
7723#[derive(Clone, PartialEq, ::prost::Message)]
7724pub struct UpdateTemplateRequest {
7725 /// ID of the template to update.
7726 #[prost(string, tag="1")]
7727 pub template_id: ::prost::alloc::string::String,
7728 /// New template body with {{variable}} placeholders.
7729 /// Constraints: Max length 50000 characters.
7730 #[prost(string, tag="2")]
7731 pub body: ::prost::alloc::string::String,
7732 /// Updated variables for substitution.
7733 #[prost(message, repeated, tag="3")]
7734 pub variables: ::prost::alloc::vec::Vec<TemplateVariable>,
7735}
7736/// Response after updating a template.
7737#[derive(Clone, PartialEq, ::prost::Message)]
7738pub struct UpdateTemplateResponse {
7739 /// The updated template with incremented version number.
7740 #[prost(message, optional, tag="1")]
7741 pub template: ::core::option::Option<Template>,
7742}
7743/// Request to retrieve a specific template version.
7744#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7745pub struct GetTemplateRequest {
7746 /// ID of the template to retrieve.
7747 #[prost(string, tag="1")]
7748 pub template_id: ::prost::alloc::string::String,
7749 /// Version to retrieve. 0 returns the latest version.
7750 #[prost(int32, tag="2")]
7751 pub version: i32,
7752}
7753/// Response containing the requested template.
7754#[derive(Clone, PartialEq, ::prost::Message)]
7755pub struct GetTemplateResponse {
7756 /// The requested template.
7757 #[prost(message, optional, tag="1")]
7758 pub template: ::core::option::Option<Template>,
7759}
7760/// Request to list templates with pagination.
7761#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7762pub struct ListTemplatesRequest {
7763 /// Pagination parameters.
7764 #[prost(message, optional, tag="1")]
7765 pub pagination: ::core::option::Option<Pagination>,
7766 /// Filter by template type. UNSPECIFIED returns all templates.
7767 #[prost(enumeration="TemplateType", tag="2")]
7768 pub r#type: i32,
7769}
7770/// Response containing a page of templates.
7771#[derive(Clone, PartialEq, ::prost::Message)]
7772pub struct ListTemplatesResponse {
7773 /// List of templates in this page (latest version of each).
7774 #[prost(message, repeated, tag="1")]
7775 pub templates: ::prost::alloc::vec::Vec<Template>,
7776 /// Pagination metadata for fetching subsequent pages.
7777 #[prost(message, optional, tag="2")]
7778 pub pagination_meta: ::core::option::Option<PaginationMeta>,
7779}
7780/// Request to create a translation for a template.
7781#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7782pub struct CreateTemplateTranslationRequest {
7783 /// ID of the template to translate.
7784 #[prost(string, tag="1")]
7785 pub template_id: ::prost::alloc::string::String,
7786 /// Version of the template to translate.
7787 #[prost(int32, tag="2")]
7788 pub version: i32,
7789 /// Target locale.
7790 #[prost(string, tag="3")]
7791 pub locale: ::prost::alloc::string::String,
7792 /// Translated title.
7793 #[prost(string, tag="4")]
7794 pub title: ::prost::alloc::string::String,
7795 /// Translated body content.
7796 #[prost(string, tag="5")]
7797 pub body: ::prost::alloc::string::String,
7798 /// Who created this translation ("ai:bedrock" or user UUID).
7799 #[prost(string, tag="6")]
7800 pub translated_by: ::prost::alloc::string::String,
7801 /// Initial status (typically DRAFT or AI_TRANSLATED).
7802 #[prost(enumeration="TranslationStatus", tag="7")]
7803 pub status: i32,
7804}
7805/// Response after creating a template translation.
7806#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7807pub struct CreateTemplateTranslationResponse {
7808 /// The created translation.
7809 #[prost(message, optional, tag="1")]
7810 pub translation: ::core::option::Option<TemplateTranslation>,
7811}
7812/// Request to update an existing template translation.
7813#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7814pub struct UpdateTemplateTranslationRequest {
7815 /// ID of the translation to update.
7816 #[prost(string, tag="1")]
7817 pub translation_id: ::prost::alloc::string::String,
7818 /// Updated title. Empty leaves unchanged.
7819 #[prost(string, tag="2")]
7820 pub title: ::prost::alloc::string::String,
7821 /// Updated body. Empty leaves unchanged.
7822 #[prost(string, tag="3")]
7823 pub body: ::prost::alloc::string::String,
7824 /// Updated status.
7825 #[prost(enumeration="TranslationStatus", tag="4")]
7826 pub status: i32,
7827}
7828/// Response after updating a template translation.
7829#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7830pub struct UpdateTemplateTranslationResponse {
7831 /// The updated translation.
7832 #[prost(message, optional, tag="1")]
7833 pub translation: ::core::option::Option<TemplateTranslation>,
7834}
7835/// Request to list translations for a template version.
7836#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7837pub struct ListTemplateTranslationsRequest {
7838 /// ID of the template.
7839 #[prost(string, tag="1")]
7840 pub template_id: ::prost::alloc::string::String,
7841 /// Version of the template. 0 returns translations for the latest version.
7842 #[prost(int32, tag="2")]
7843 pub version: i32,
7844}
7845/// Response containing all translations for a template version.
7846#[derive(Clone, PartialEq, ::prost::Message)]
7847pub struct ListTemplateTranslationsResponse {
7848 /// Translations for the requested template version.
7849 #[prost(message, repeated, tag="1")]
7850 pub translations: ::prost::alloc::vec::Vec<TemplateTranslation>,
7851}
7852/// Request to approve a template translation.
7853#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7854pub struct ApproveTemplateTranslationRequest {
7855 /// ID of the translation to approve.
7856 #[prost(string, tag="1")]
7857 pub translation_id: ::prost::alloc::string::String,
7858}
7859/// Response after approving a template translation.
7860#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7861pub struct ApproveTemplateTranslationResponse {
7862 /// The approved translation (status: APPROVED, reviewed_by and reviewed_at set).
7863 #[prost(message, optional, tag="1")]
7864 pub translation: ::core::option::Option<TemplateTranslation>,
7865}
7866// ─── Enums ──────────────────────────────────────────────────────────────────
7867
7868/// Content format of a template, determining which editor and renderer to use.
7869#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
7870#[repr(i32)]
7871pub enum TemplateType {
7872 /// Default value; treated as MARKDOWN for backward compatibility.
7873 Unspecified = 0,
7874 /// Markdown with {{variable}} placeholders.
7875 Markdown = 1,
7876 /// Rich text format (reserved for future use).
7877 Rich = 2,
7878 /// Raw HTML format (reserved for future use).
7879 Html = 3,
7880}
7881impl TemplateType {
7882 /// String value of the enum field names used in the ProtoBuf definition.
7883 ///
7884 /// The values are not transformed in any way and thus are considered stable
7885 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
7886 pub fn as_str_name(&self) -> &'static str {
7887 match self {
7888 Self::Unspecified => "TEMPLATE_TYPE_UNSPECIFIED",
7889 Self::Markdown => "TEMPLATE_TYPE_MARKDOWN",
7890 Self::Rich => "TEMPLATE_TYPE_RICH",
7891 Self::Html => "TEMPLATE_TYPE_HTML",
7892 }
7893 }
7894 /// Creates an enum from field names used in the ProtoBuf definition.
7895 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
7896 match value {
7897 "TEMPLATE_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
7898 "TEMPLATE_TYPE_MARKDOWN" => Some(Self::Markdown),
7899 "TEMPLATE_TYPE_RICH" => Some(Self::Rich),
7900 "TEMPLATE_TYPE_HTML" => Some(Self::Html),
7901 _ => None,
7902 }
7903 }
7904}
7905/// Source from which a template variable's value is resolved at render time.
7906#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
7907#[repr(i32)]
7908pub enum TemplateVariableSource {
7909 /// Default value; treated as CUSTOM for backward compatibility.
7910 Unspecified = 0,
7911 /// Auto-resolved from the target user's profile attributes.
7912 Profile = 1,
7913 /// Provided manually in the campaign or workflow step configuration.
7914 Custom = 2,
7915}
7916impl TemplateVariableSource {
7917 /// String value of the enum field names used in the ProtoBuf definition.
7918 ///
7919 /// The values are not transformed in any way and thus are considered stable
7920 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
7921 pub fn as_str_name(&self) -> &'static str {
7922 match self {
7923 Self::Unspecified => "TEMPLATE_VARIABLE_SOURCE_UNSPECIFIED",
7924 Self::Profile => "TEMPLATE_VARIABLE_SOURCE_PROFILE",
7925 Self::Custom => "TEMPLATE_VARIABLE_SOURCE_CUSTOM",
7926 }
7927 }
7928 /// Creates an enum from field names used in the ProtoBuf definition.
7929 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
7930 match value {
7931 "TEMPLATE_VARIABLE_SOURCE_UNSPECIFIED" => Some(Self::Unspecified),
7932 "TEMPLATE_VARIABLE_SOURCE_PROFILE" => Some(Self::Profile),
7933 "TEMPLATE_VARIABLE_SOURCE_CUSTOM" => Some(Self::Custom),
7934 _ => None,
7935 }
7936 }
7937}
7938/// Review status of a template translation.
7939#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
7940#[repr(i32)]
7941pub enum TranslationStatus {
7942 Unspecified = 0,
7943 /// Translation draft, not yet reviewed.
7944 Draft = 1,
7945 /// Translation generated by AI, pending human review.
7946 AiTranslated = 2,
7947 /// Translation is being reviewed by a human.
7948 InReview = 3,
7949 /// Translation has been approved for use.
7950 Approved = 4,
7951}
7952impl TranslationStatus {
7953 /// String value of the enum field names used in the ProtoBuf definition.
7954 ///
7955 /// The values are not transformed in any way and thus are considered stable
7956 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
7957 pub fn as_str_name(&self) -> &'static str {
7958 match self {
7959 Self::Unspecified => "TRANSLATION_STATUS_UNSPECIFIED",
7960 Self::Draft => "TRANSLATION_STATUS_DRAFT",
7961 Self::AiTranslated => "TRANSLATION_STATUS_AI_TRANSLATED",
7962 Self::InReview => "TRANSLATION_STATUS_IN_REVIEW",
7963 Self::Approved => "TRANSLATION_STATUS_APPROVED",
7964 }
7965 }
7966 /// Creates an enum from field names used in the ProtoBuf definition.
7967 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
7968 match value {
7969 "TRANSLATION_STATUS_UNSPECIFIED" => Some(Self::Unspecified),
7970 "TRANSLATION_STATUS_DRAFT" => Some(Self::Draft),
7971 "TRANSLATION_STATUS_AI_TRANSLATED" => Some(Self::AiTranslated),
7972 "TRANSLATION_STATUS_IN_REVIEW" => Some(Self::InReview),
7973 "TRANSLATION_STATUS_APPROVED" => Some(Self::Approved),
7974 _ => None,
7975 }
7976 }
7977}
7978// ─── Messages ───────────────────────────────────────────────────────────────
7979
7980/// Decoded deeplink-token payload. Populated by ValidateDeeplinkToken
7981/// only when validation succeeds.
7982#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
7983pub struct DeeplinkTokenPayload {
7984 /// Campaign UUID the deeplink targets. The native app uses this for the
7985 /// authenticated GetCampaign follow-up post-recipient-auth.
7986 #[prost(string, tag="1")]
7987 pub campaign_id: ::prost::alloc::string::String,
7988 /// Recipient UUID the token authorizes. The token does not authenticate
7989 /// the recipient (that's the auth flow's job); it authorizes "this
7990 /// deeplink path is for this recipient" so the native app can refuse
7991 /// to render a token whose embedded recipient mismatches the signed-in
7992 /// user.
7993 #[prost(string, tag="2")]
7994 pub recipient_user_id: ::prost::alloc::string::String,
7995 /// Step kind the deeplink targets — REMINDER vs ESCALATION. Lets the
7996 /// native app pick the right campaign-card variant before the auth
7997 /// gate.
7998 #[prost(enumeration="ChannelStepKind", tag="3")]
7999 pub step_kind: i32,
8000 /// Expiry the token carries. Validation rejects tokens past this time
8001 /// even if the signature checks out.
8002 #[prost(message, optional, tag="4")]
8003 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
8004}
8005#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8006pub struct SignDeeplinkTokenRequest {
8007 /// Campaign whose deeplink this token authorizes. Constraints: required,
8008 /// must be a UUID and exist within the caller's organization.
8009 #[prost(string, tag="1")]
8010 pub campaign_id: ::prost::alloc::string::String,
8011 /// Recipient the token authorizes. Constraints: required, must be a UUID
8012 /// and a member of the campaign's audience.
8013 #[prost(string, tag="2")]
8014 pub recipient_user_id: ::prost::alloc::string::String,
8015 /// Step kind the deeplink targets. Required.
8016 #[prost(enumeration="ChannelStepKind", tag="3")]
8017 pub step_kind: i32,
8018 /// Token lifetime in seconds from now. Constraints: required, must be
8019 /// in (0, 30 * 24 * 3600] (1 second to 30 days). 30 days matches the
8020 /// platform's outer bound on actionable campaign lifetimes; longer
8021 /// tokens are not signed.
8022 #[prost(int64, tag="4")]
8023 pub ttl_seconds: i64,
8024}
8025#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8026pub struct SignDeeplinkTokenResponse {
8027 /// The signed token, ready to URL-embed in
8028 /// links.pidgr.com/c/{short_code}?t={token}. Format: base64url-encoded
8029 /// payload (JSON) + base64url-encoded HMAC-SHA256 trailer, joined by
8030 /// a single dot. Implementation detail — clients SHOULD NOT parse or
8031 /// mutate the token; they pass it back to ValidateDeeplinkToken.
8032 #[prost(string, tag="1")]
8033 pub token: ::prost::alloc::string::String,
8034 /// The expiry the token carries. Echoed back so clients don't need to
8035 /// redo the time-math the caller passed in via ttl_seconds.
8036 #[prost(message, optional, tag="2")]
8037 pub expires_at: ::core::option::Option<::prost_types::Timestamp>,
8038 /// The platform key version used to sign. Clients MAY record for
8039 /// telemetry but SHOULD NOT branch logic on it — the platform manages
8040 /// overlap windows during rotation transparently.
8041 #[prost(int32, tag="3")]
8042 pub key_version: i32,
8043}
8044#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8045pub struct ValidateDeeplinkTokenRequest {
8046 /// The token bytes from the deeplink URL's `t` query parameter.
8047 /// Constraints: required, non-empty.
8048 #[prost(string, tag="1")]
8049 pub token: ::prost::alloc::string::String,
8050 /// Campaign UUID embedded in the URL path (translated from the
8051 /// short-code by the native app via CampaignService.GetCampaignByShortCode).
8052 /// Validation rejects when the token's embedded campaign_id does not
8053 /// match — defense against replay attacks that swap the short-code
8054 /// path component while reusing a signed token from a different
8055 /// campaign.
8056 #[prost(string, tag="2")]
8057 pub campaign_id: ::prost::alloc::string::String,
8058}
8059#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8060pub struct ValidateDeeplinkTokenResponse {
8061 /// True when signature + expiry both check out under any active or
8062 /// overlap-window key version.
8063 #[prost(bool, tag="1")]
8064 pub valid: bool,
8065 /// Reason validation failed. Set only when valid=false; UNSPECIFIED
8066 /// when valid=true. The native app uses this to drive UX (silent retry
8067 /// vs. "this link expired" message vs. "this link looks tampered").
8068 #[prost(enumeration="ValidationFailureReason", tag="2")]
8069 pub failure_reason: i32,
8070 /// Decoded payload. Populated only when valid=true. The native app
8071 /// SHOULD compare payload.recipient_user_id against the signed-in user
8072 /// and refuse to render the campaign card on mismatch.
8073 #[prost(message, optional, tag="3")]
8074 pub payload: ::core::option::Option<DeeplinkTokenPayload>,
8075}
8076// ─── Enums ──────────────────────────────────────────────────────────────────
8077
8078/// Reason a deeplink-token validation failed. Empty when valid=true.
8079#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
8080#[repr(i32)]
8081pub enum ValidationFailureReason {
8082 Unspecified = 0,
8083 /// Token bytes parsed but the HMAC signature did not verify under any
8084 /// active or overlap-window key version.
8085 InvalidSignature = 1,
8086 /// Token signature verified but its embedded expiry has passed.
8087 Expired = 2,
8088 /// Signature would have verified, but the key version that signed the
8089 /// token is past the rotation overlap window and has been hard-deleted.
8090 /// This means the token is older than the platform's retention bound
8091 /// (rotation cadence + overlap window) — operationally equivalent to
8092 /// EXPIRED but distinguishable for telemetry.
8093 KeyRetired = 3,
8094 /// Token bytes could not be parsed at all (not base64url, wrong length,
8095 /// missing payload separator, etc.). Indicates a tampered or
8096 /// truncated URL.
8097 Malformed = 4,
8098}
8099impl ValidationFailureReason {
8100 /// String value of the enum field names used in the ProtoBuf definition.
8101 ///
8102 /// The values are not transformed in any way and thus are considered stable
8103 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
8104 pub fn as_str_name(&self) -> &'static str {
8105 match self {
8106 Self::Unspecified => "VALIDATION_FAILURE_REASON_UNSPECIFIED",
8107 Self::InvalidSignature => "VALIDATION_FAILURE_REASON_INVALID_SIGNATURE",
8108 Self::Expired => "VALIDATION_FAILURE_REASON_EXPIRED",
8109 Self::KeyRetired => "VALIDATION_FAILURE_REASON_KEY_RETIRED",
8110 Self::Malformed => "VALIDATION_FAILURE_REASON_MALFORMED",
8111 }
8112 }
8113 /// Creates an enum from field names used in the ProtoBuf definition.
8114 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
8115 match value {
8116 "VALIDATION_FAILURE_REASON_UNSPECIFIED" => Some(Self::Unspecified),
8117 "VALIDATION_FAILURE_REASON_INVALID_SIGNATURE" => Some(Self::InvalidSignature),
8118 "VALIDATION_FAILURE_REASON_EXPIRED" => Some(Self::Expired),
8119 "VALIDATION_FAILURE_REASON_KEY_RETIRED" => Some(Self::KeyRetired),
8120 "VALIDATION_FAILURE_REASON_MALFORMED" => Some(Self::Malformed),
8121 _ => None,
8122 }
8123 }
8124}
8125// ─── Messages ───────────────────────────────────────────────────────────────
8126
8127/// One recorded observation of an indicator over a period.
8128///
8129/// A reading records what was reported and nothing else. Reading it
8130/// together with the response rate of the campaign it followed produces
8131/// an interpretation — for instance that a well-acknowledged message
8132/// nonetheless changed nothing, which says the gap was never one of
8133/// direction. That crossing is analysis and belongs to the diagnosis
8134/// layer; storing it here would make the record and its interpretation
8135/// impossible to tell apart, and would freeze one interpretation into
8136/// data that later analysis cannot revisit.
8137#[derive(Clone, PartialEq, ::prost::Message)]
8138pub struct IndicatorReading {
8139 /// Unique identifier for the reading.
8140 #[prost(string, tag="1")]
8141 pub id: ::prost::alloc::string::String,
8142 /// Indicator this reading was recorded against.
8143 #[prost(string, tag="2")]
8144 pub indicator_id: ::prost::alloc::string::String,
8145 /// Kind of source that produced it.
8146 #[prost(enumeration="ReadingSource", tag="3")]
8147 pub source: i32,
8148 /// What the reading says.
8149 #[prost(enumeration="ReadingOutcome", tag="4")]
8150 pub outcome: i32,
8151 /// Start of the period the reading covers.
8152 #[prost(message, optional, tag="5")]
8153 pub period_start: ::core::option::Option<::prost_types::Timestamp>,
8154 /// End of the period the reading covers.
8155 #[prost(message, optional, tag="6")]
8156 pub period_end: ::core::option::Option<::prost_types::Timestamp>,
8157 /// Verification run that produced it. Set only when `source` is
8158 /// READING_SOURCE_VERIFICATION_CAMPAIGN, and the way to check the
8159 /// reading: the run carries how many verifiers were asked and over
8160 /// what window, never who they were. The identities are deliberately
8161 /// not recorded, because the reading is about a unit and not about its
8162 /// members, and keeping the two apart is what stops a stored answer
8163 /// from becoming one person's judgement of another.
8164 #[prost(string, tag="7")]
8165 pub verification_run_id: ::prost::alloc::string::String,
8166 /// Campaign whose responses produced it. For an in-app reading this is
8167 /// the campaign the audience answered; for a verification reading it
8168 /// is the follow-up that was sent to the verifiers.
8169 #[prost(string, tag="8")]
8170 pub campaign_id: ::prost::alloc::string::String,
8171 /// How many responses fed this reading. For a verification reading the
8172 /// unit of count is the organizational unit that answered, not the
8173 /// person: the question is asked once per unit.
8174 ///
8175 /// Absent for a source that does not count responses at all, such as a
8176 /// figure pushed from another system. Absence and a count of none are
8177 /// different facts and the field carries presence so they stay
8178 /// different.
8179 #[prost(int32, optional, tag="9")]
8180 pub response_count: ::core::option::Option<i32>,
8181 /// How many responses were expected over the same period. Travels with
8182 /// `response_count` so that the reading carries its own denominator
8183 /// and can be judged without a second lookup, and carries presence for
8184 /// the same reason.
8185 #[prost(int32, optional, tag="10")]
8186 pub expected_response_count: ::core::option::Option<i32>,
8187 /// Timestamp when the reading was stored.
8188 #[prost(message, optional, tag="11")]
8189 pub recorded_at: ::core::option::Option<::prost_types::Timestamp>,
8190 /// The measured figure, expressed in the indicator's unit and read
8191 /// together with its direction and target.
8192 ///
8193 /// Present only for a source that produces a number: a figure pushed
8194 /// from one of the organization's own systems, or one entered by hand.
8195 /// A verification-campaign reading never carries one, because the
8196 /// question put to a verifier is whether the behaviour changed and an
8197 /// answer to that has no magnitude — deriving a figure from it would
8198 /// manufacture precision the answer does not contain. Absent for every
8199 /// source that has no number to report, which is not the same as a
8200 /// measurement of zero.
8201 #[prost(double, optional, tag="12")]
8202 pub value: ::core::option::Option<f64>,
8203}
8204/// A scheduled follow-up that asks whether the behaviour a campaign was
8205/// trying to change actually changed, and lands the answer on an
8206/// indicator.
8207///
8208/// The question is asked about an organizational unit, never about a
8209/// named person. A run therefore never produces a third party's judgement
8210/// of an individual, which is a category of data this contract does not
8211/// carry.
8212#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8213pub struct VerificationRun {
8214 /// Unique identifier for the run.
8215 #[prost(string, tag="1")]
8216 pub id: ::prost::alloc::string::String,
8217 /// Campaign whose effect is being verified.
8218 #[prost(string, tag="2")]
8219 pub campaign_id: ::prost::alloc::string::String,
8220 /// Indicator the answers are recorded against.
8221 #[prost(string, tag="3")]
8222 pub indicator_id: ::prost::alloc::string::String,
8223 /// Objective the indicator hangs from, carried here so a run can be
8224 /// listed and read at the objective level without resolving the
8225 /// indicator first.
8226 #[prost(string, tag="4")]
8227 pub objective_id: ::prost::alloc::string::String,
8228 /// Lifecycle state.
8229 #[prost(enumeration="VerificationRunState", tag="5")]
8230 pub state: i32,
8231 /// The follow-up campaign sent to the verifiers. Empty while the run
8232 /// is VERIFICATION_RUN_STATE_PENDING, because it does not exist yet.
8233 #[prost(string, tag="6")]
8234 pub verification_campaign_id: ::prost::alloc::string::String,
8235 /// When the follow-up is due, derived from the wait declared on the
8236 /// indicator's evidence source. Known from the moment the run is
8237 /// created.
8238 #[prost(message, optional, tag="7")]
8239 pub scheduled_for: ::core::option::Option<::prost_types::Timestamp>,
8240 /// When the follow-up actually went out and collection opened. Unset
8241 /// while the run is pending.
8242 #[prost(message, optional, tag="8")]
8243 pub window_start: ::core::option::Option<::prost_types::Timestamp>,
8244 /// When collection closed. Unset until the run is complete.
8245 #[prost(message, optional, tag="9")]
8246 pub window_end: ::core::option::Option<::prost_types::Timestamp>,
8247 /// How many verifiers the derivation resolved to, after dropping
8248 /// anyone who is inside the audience being measured and after any unit
8249 /// too small to be asked about on its own was folded into the level
8250 /// above it.
8251 #[prost(int32, tag="10")]
8252 pub verifier_count: i32,
8253 /// Reading this run produced. Empty until the run completes, and
8254 /// empty on a completed run that produced none — a run nobody answered
8255 /// leaves the indicator without evidence rather than with a zero.
8256 #[prost(string, tag="11")]
8257 pub reading_id: ::prost::alloc::string::String,
8258 /// Timestamp when the run was created.
8259 #[prost(message, optional, tag="12")]
8260 pub created_at: ::core::option::Option<::prost_types::Timestamp>,
8261 /// Timestamp when the run was last updated.
8262 #[prost(message, optional, tag="13")]
8263 pub updated_at: ::core::option::Option<::prost_types::Timestamp>,
8264}
8265/// Request to schedule a verification run for a campaign and one of the
8266/// indicators it should move.
8267#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8268pub struct StartVerificationRunRequest {
8269 /// Campaign whose effect is to be verified. Required.
8270 #[prost(string, tag="1")]
8271 pub campaign_id: ::prost::alloc::string::String,
8272 /// Indicator the answers will be recorded against. Required. Its
8273 /// evidence source must be the verification-campaign kind; any other
8274 /// kind returns FAILED_PRECONDITION, because the wait, the verifier
8275 /// derivation and the follow-up template all come from that
8276 /// configuration and have nowhere else to come from.
8277 #[prost(string, tag="2")]
8278 pub indicator_id: ::prost::alloc::string::String,
8279}
8280/// Response after scheduling a verification run.
8281#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8282pub struct StartVerificationRunResponse {
8283 /// The scheduled run. Scheduling a run for a pair that already has one
8284 /// that has not completed is idempotent and returns the existing run.
8285 #[prost(message, optional, tag="1")]
8286 pub run: ::core::option::Option<VerificationRun>,
8287}
8288/// Request to retrieve one verification run.
8289#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8290pub struct GetVerificationRunRequest {
8291 /// ID of the run to retrieve. Required.
8292 #[prost(string, tag="1")]
8293 pub verification_run_id: ::prost::alloc::string::String,
8294}
8295/// Response containing the requested verification run.
8296#[derive(Clone, PartialEq, ::prost::Message)]
8297pub struct GetVerificationRunResponse {
8298 /// The requested run.
8299 #[prost(message, optional, tag="1")]
8300 pub run: ::core::option::Option<VerificationRun>,
8301 /// The reading it produced, when it produced one. Absent while the run
8302 /// is still open and absent on a completed run that collected nothing.
8303 #[prost(message, optional, tag="2")]
8304 pub reading: ::core::option::Option<IndicatorReading>,
8305}
8306/// Request to list verification runs. Exactly one of `objective_id`,
8307/// `indicator_id` and `campaign_id` must be set; sending more than one,
8308/// or none, returns INVALID_ARGUMENT.
8309#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8310pub struct ListVerificationRunsRequest {
8311 /// List the runs recorded against the indicators of this objective.
8312 #[prost(string, optional, tag="1")]
8313 pub objective_id: ::core::option::Option<::prost::alloc::string::String>,
8314 /// List the runs recorded against this indicator.
8315 #[prost(string, optional, tag="2")]
8316 pub indicator_id: ::core::option::Option<::prost::alloc::string::String>,
8317 /// List the runs verifying this campaign.
8318 #[prost(string, optional, tag="3")]
8319 pub campaign_id: ::core::option::Option<::prost::alloc::string::String>,
8320 /// Return only runs in this state. Unspecified returns every state.
8321 #[prost(enumeration="VerificationRunState", tag="4")]
8322 pub state: i32,
8323 /// Pagination parameters.
8324 #[prost(message, optional, tag="5")]
8325 pub pagination: ::core::option::Option<Pagination>,
8326}
8327/// Response containing a page of verification runs.
8328#[derive(Clone, PartialEq, ::prost::Message)]
8329pub struct ListVerificationRunsResponse {
8330 /// Runs in this page, newest first.
8331 #[prost(message, repeated, tag="1")]
8332 pub runs: ::prost::alloc::vec::Vec<VerificationRun>,
8333 /// Pagination metadata for fetching subsequent pages.
8334 #[prost(message, optional, tag="2")]
8335 pub pagination_meta: ::core::option::Option<PaginationMeta>,
8336}
8337/// Request to list the readings recorded against one indicator.
8338#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
8339pub struct ListIndicatorReadingsRequest {
8340 /// Indicator whose readings to list. Required.
8341 #[prost(string, tag="1")]
8342 pub indicator_id: ::prost::alloc::string::String,
8343 /// Return only readings from this kind of source. Unspecified returns
8344 /// every kind.
8345 #[prost(enumeration="ReadingSource", tag="2")]
8346 pub source: i32,
8347 /// Pagination parameters.
8348 #[prost(message, optional, tag="3")]
8349 pub pagination: ::core::option::Option<Pagination>,
8350 /// Return only readings whose period ends at or after this instant.
8351 /// Unset leaves the range open at that end.
8352 #[prost(message, optional, tag="4")]
8353 pub period_start_after: ::core::option::Option<::prost_types::Timestamp>,
8354 /// Return only readings whose period starts at or before this instant.
8355 /// Unset leaves the range open at that end.
8356 #[prost(message, optional, tag="5")]
8357 pub period_end_before: ::core::option::Option<::prost_types::Timestamp>,
8358}
8359/// Response containing a page of readings.
8360#[derive(Clone, PartialEq, ::prost::Message)]
8361pub struct ListIndicatorReadingsResponse {
8362 /// Readings in this page, newest period first. An empty page means no
8363 /// reading exists for the filter, which is a statement about evidence
8364 /// and not about the indicator's value.
8365 #[prost(message, repeated, tag="1")]
8366 pub readings: ::prost::alloc::vec::Vec<IndicatorReading>,
8367 /// Pagination metadata for fetching subsequent pages.
8368 #[prost(message, optional, tag="2")]
8369 pub pagination_meta: ::core::option::Option<PaginationMeta>,
8370}
8371// ─── Enums ──────────────────────────────────────────────────────────────────
8372
8373/// Where a reading came from. One value per evidence adapter, so that a
8374/// reading can always be traced back to the kind of source that produced
8375/// it without consulting the indicator's current configuration — an
8376/// indicator's evidence source can be changed after readings exist, and
8377/// past readings keep saying how they were actually obtained.
8378#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
8379#[repr(i32)]
8380pub enum ReadingSource {
8381 Unspecified = 0,
8382 /// Produced by responses from the audience of the message itself.
8383 InApp = 1,
8384 /// Produced by a deferred follow-up message asking someone other than
8385 /// the audience whether the behaviour changed.
8386 VerificationCampaign = 2,
8387 /// Pushed by the organization from one of its own systems.
8388 Webhook = 3,
8389 /// Entered by hand or imported from a spreadsheet.
8390 ManualEntry = 4,
8391}
8392impl ReadingSource {
8393 /// String value of the enum field names used in the ProtoBuf definition.
8394 ///
8395 /// The values are not transformed in any way and thus are considered stable
8396 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
8397 pub fn as_str_name(&self) -> &'static str {
8398 match self {
8399 Self::Unspecified => "READING_SOURCE_UNSPECIFIED",
8400 Self::InApp => "READING_SOURCE_IN_APP",
8401 Self::VerificationCampaign => "READING_SOURCE_VERIFICATION_CAMPAIGN",
8402 Self::Webhook => "READING_SOURCE_WEBHOOK",
8403 Self::ManualEntry => "READING_SOURCE_MANUAL_ENTRY",
8404 }
8405 }
8406 /// Creates an enum from field names used in the ProtoBuf definition.
8407 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
8408 match value {
8409 "READING_SOURCE_UNSPECIFIED" => Some(Self::Unspecified),
8410 "READING_SOURCE_IN_APP" => Some(Self::InApp),
8411 "READING_SOURCE_VERIFICATION_CAMPAIGN" => Some(Self::VerificationCampaign),
8412 "READING_SOURCE_WEBHOOK" => Some(Self::Webhook),
8413 "READING_SOURCE_MANUAL_ENTRY" => Some(Self::ManualEntry),
8414 _ => None,
8415 }
8416 }
8417}
8418/// What a reading says about the indicator it was recorded against.
8419/// Every reading carries one, whatever produced it, so that sources of
8420/// different shapes remain comparable on the only question the indicator
8421/// is there to answer.
8422///
8423/// For a verification-campaign reading this is the whole of it. A
8424/// verifier is asked whether the behaviour changed for a unit, not to
8425/// grade it, so a three-way judgement is all the answer contains and
8426/// anything finer would be invented; those readings therefore carry no
8427/// figure. A source that genuinely measures something — a system of the
8428/// organization's own, or a figure entered by hand — reports the number
8429/// in `value` in addition, and the outcome then says how that number
8430/// reads against the indicator's direction and target.
8431#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
8432#[repr(i32)]
8433pub enum ReadingOutcome {
8434 Unspecified = 0,
8435 /// The behaviour the indicator describes was reported as happening.
8436 Positive = 1,
8437 /// The behaviour the indicator describes was reported as not
8438 /// happening. A negative reading is a finding, not a failure to
8439 /// collect.
8440 Negative = 2,
8441 /// Answers were collected but they do not support either reading —
8442 /// too few came back, or they disagreed.
8443 ///
8444 /// Distinct from no reading at all. When nobody answers, no reading is
8445 /// recorded and the indicator simply has no evidence for that period;
8446 /// silence is never stored as an outcome, and never as a zero.
8447 Insufficient = 3,
8448}
8449impl ReadingOutcome {
8450 /// String value of the enum field names used in the ProtoBuf definition.
8451 ///
8452 /// The values are not transformed in any way and thus are considered stable
8453 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
8454 pub fn as_str_name(&self) -> &'static str {
8455 match self {
8456 Self::Unspecified => "READING_OUTCOME_UNSPECIFIED",
8457 Self::Positive => "READING_OUTCOME_POSITIVE",
8458 Self::Negative => "READING_OUTCOME_NEGATIVE",
8459 Self::Insufficient => "READING_OUTCOME_INSUFFICIENT",
8460 }
8461 }
8462 /// Creates an enum from field names used in the ProtoBuf definition.
8463 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
8464 match value {
8465 "READING_OUTCOME_UNSPECIFIED" => Some(Self::Unspecified),
8466 "READING_OUTCOME_POSITIVE" => Some(Self::Positive),
8467 "READING_OUTCOME_NEGATIVE" => Some(Self::Negative),
8468 "READING_OUTCOME_INSUFFICIENT" => Some(Self::Insufficient),
8469 _ => None,
8470 }
8471 }
8472}
8473/// Lifecycle of a verification run.
8474#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
8475#[repr(i32)]
8476pub enum VerificationRunState {
8477 Unspecified = 0,
8478 /// Scheduled. The wait after the original message has not elapsed and
8479 /// the follow-up has not been sent.
8480 Pending = 1,
8481 /// The follow-up has been sent and answers are being collected.
8482 Collecting = 2,
8483 /// Collection is closed. The run either produced a reading or produced
8484 /// none; both are terminal, and the second is not an error.
8485 Complete = 3,
8486}
8487impl VerificationRunState {
8488 /// String value of the enum field names used in the ProtoBuf definition.
8489 ///
8490 /// The values are not transformed in any way and thus are considered stable
8491 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
8492 pub fn as_str_name(&self) -> &'static str {
8493 match self {
8494 Self::Unspecified => "VERIFICATION_RUN_STATE_UNSPECIFIED",
8495 Self::Pending => "VERIFICATION_RUN_STATE_PENDING",
8496 Self::Collecting => "VERIFICATION_RUN_STATE_COLLECTING",
8497 Self::Complete => "VERIFICATION_RUN_STATE_COMPLETE",
8498 }
8499 }
8500 /// Creates an enum from field names used in the ProtoBuf definition.
8501 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
8502 match value {
8503 "VERIFICATION_RUN_STATE_UNSPECIFIED" => Some(Self::Unspecified),
8504 "VERIFICATION_RUN_STATE_PENDING" => Some(Self::Pending),
8505 "VERIFICATION_RUN_STATE_COLLECTING" => Some(Self::Collecting),
8506 "VERIFICATION_RUN_STATE_COMPLETE" => Some(Self::Complete),
8507 _ => None,
8508 }
8509 }
8510}
8511include!("pidgr.v1.tonic.rs");
8512// @@protoc_insertion_point(module)