1use crate::WriteSpaceTarget;
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11pub struct StoreMemoryRequest {
12 pub content: String,
13 #[serde(default)]
14 pub memory_type: Option<String>,
15 #[serde(
16 default,
17 alias = "domain",
18 skip_serializing_if = "WriteSpaceTarget::is_inherit"
19 )]
20 pub space: WriteSpaceTarget,
21 #[serde(default)]
22 pub source_agent: Option<String>,
23 #[serde(default)]
24 pub title: Option<String>,
25 #[serde(default)]
26 pub confidence: Option<f32>,
27 #[serde(default)]
28 pub supersedes: Option<String>,
29 #[serde(default)]
31 pub entity: Option<String>,
32 #[serde(default)]
34 pub entity_id: Option<String>,
35 #[serde(default)]
36 pub structured_fields: Option<serde_json::Value>,
37 #[serde(default)]
38 pub retrieval_cue: Option<String>,
39}
40
41#[derive(Debug, Serialize, Deserialize)]
42pub struct SearchMemoryRequest {
43 pub query: String,
44 #[serde(default = "default_limit")]
45 pub limit: usize,
46 #[serde(default)]
47 pub memory_type: Option<String>,
48 #[serde(default, alias = "domain")]
49 pub space: Option<String>,
50 #[serde(default)]
51 pub source_agent: Option<String>,
52 #[serde(default)]
59 pub rerank: bool,
60}
61
62#[derive(Debug, Serialize, Deserialize)]
63pub struct ListMemoriesRequest {
64 #[serde(default)]
65 pub memory_type: Option<String>,
66 #[serde(default, alias = "domain")]
67 pub space: Option<String>,
68 #[serde(default = "default_list_limit")]
69 pub limit: usize,
70 #[serde(default, skip_serializing_if = "Option::is_none")]
71 pub confirmed: Option<bool>,
72}
73
74#[derive(Debug, Serialize, Deserialize)]
75pub struct ConfirmRequest {
76 #[serde(default = "default_confirmed")]
77 pub confirmed: bool,
78}
79
80#[derive(Debug, Serialize, Deserialize)]
81pub struct ReclassifyMemoryRequest {
82 pub memory_type: String,
83}
84
85#[derive(Debug, Serialize, Deserialize)]
86pub struct ImportMemoriesRequest {
87 pub source: String,
88 pub content: String,
89 #[serde(default)]
90 pub label: Option<String>,
91 #[serde(default, skip_serializing_if = "WriteSpaceTarget::is_inherit")]
92 pub space: WriteSpaceTarget,
93}
94
95#[derive(Debug, Serialize, Deserialize)]
98pub struct SearchRequest {
99 pub query: String,
100 #[serde(default = "default_limit")]
101 pub limit: usize,
102 pub source_filter: Option<String>,
103 #[serde(default, alias = "domain")]
104 pub space: Option<String>,
105}
106
107#[doc(hidden)]
108#[derive(Debug, Serialize, Deserialize)]
109pub struct ContextRequest {
110 pub current_file: String,
111 pub cursor_prefix: String,
112 #[serde(default = "default_limit")]
113 pub limit: usize,
114}
115
116#[derive(Debug, Serialize, Deserialize)]
117pub struct ChatContextRequest {
118 #[serde(default)]
119 pub query: Option<String>,
120 #[serde(default)]
121 pub conversation_id: Option<String>,
122 #[serde(default = "default_max_chunks")]
123 pub max_chunks: usize,
124 #[serde(default)]
125 pub relevance_threshold: Option<f64>,
126 #[deprecated(
130 since = "0.3.2",
131 note = "Goal taxonomy folded into Identity by migration 45 (Phase 0). \
132 Daemon ignores this field. Will be removed in 0.4."
133 )]
134 #[serde(default = "default_true")]
135 pub include_goals: bool,
136 #[serde(default, alias = "domain")]
137 pub space: Option<String>,
138}
139
140#[derive(Debug, Serialize, Deserialize)]
143pub struct CreateEntityRequest {
144 pub name: String,
145 pub entity_type: String,
146 #[serde(
147 default,
148 alias = "domain",
149 skip_serializing_if = "WriteSpaceTarget::is_inherit"
150 )]
151 pub space: WriteSpaceTarget,
152 #[serde(default)]
153 pub source_agent: Option<String>,
154 #[serde(default)]
155 pub confidence: Option<f32>,
156}
157
158#[doc(hidden)]
159#[derive(Debug, Serialize, Deserialize)]
160pub struct CreateRelationRequest {
161 pub from_entity: String,
162 pub to_entity: String,
163 pub relation_type: String,
164 #[serde(default)]
165 pub source_agent: Option<String>,
166 #[serde(default)]
167 pub confidence: Option<f64>,
168 #[serde(default)]
169 pub explanation: Option<String>,
170 #[serde(default)]
171 pub source_memory_id: Option<String>,
172 #[serde(default)]
177 pub span: Option<String>,
178 #[serde(default)]
181 pub model_version: Option<String>,
182 #[serde(default)]
185 pub prompt_version: Option<String>,
186}
187
188#[derive(Debug, Serialize, Deserialize)]
189pub struct AddObservationRequest {
190 pub entity_id: String,
191 pub content: String,
192 #[serde(default)]
193 pub source_agent: Option<String>,
194 #[serde(default)]
195 pub confidence: Option<f32>,
196}
197
198#[doc(hidden)]
199#[derive(Debug, Serialize, Deserialize)]
200pub struct LinkEntityRequest {
201 pub source_id: String,
202 pub entity_id: String,
203}
204
205#[derive(Debug, Serialize, Deserialize)]
206pub struct ListEntitiesRequest {
207 #[serde(default)]
208 pub entity_type: Option<String>,
209 #[serde(default, alias = "domain")]
210 pub space: Option<String>,
211}
212
213#[derive(Debug, Serialize, Deserialize)]
214pub struct SearchEntitiesRequest {
215 pub query: String,
216 #[serde(default = "default_entity_search_limit")]
217 pub limit: usize,
218}
219
220#[derive(Debug, Serialize, Deserialize)]
224pub struct MergeEntityRequest {
225 pub into: String,
226 #[serde(default)]
227 pub dry_run: bool,
228}
229
230#[derive(Debug, Serialize, Deserialize)]
233pub struct AddEntityAliasRequest {
234 pub alias: String,
235}
236
237#[derive(Debug, Serialize, Deserialize)]
240pub struct UpdateProfileRequest {
241 #[serde(default)]
242 pub name: Option<String>,
243 #[serde(default)]
244 pub display_name: Option<String>,
245 #[serde(default)]
246 pub email: Option<String>,
247 #[serde(default)]
248 pub bio: Option<String>,
249 #[serde(default)]
250 pub avatar_path: Option<String>,
251}
252
253#[derive(Debug, Serialize, Deserialize)]
254pub struct UpdateAgentRequest {
255 #[serde(default)]
256 pub agent_type: Option<String>,
257 #[serde(default)]
258 pub description: Option<String>,
259 #[serde(default)]
260 pub enabled: Option<bool>,
261 #[serde(default)]
262 pub trust_level: Option<String>,
263 #[serde(default)]
265 pub display_name: Option<String>,
266}
267
268#[derive(Debug, Serialize, Deserialize)]
271pub struct CreateSpaceRequest {
272 pub name: String,
273 pub description: Option<String>,
274}
275
276#[derive(Debug, Serialize, Deserialize)]
277pub struct UpdateSpaceRequest {
278 pub new_name: Option<String>,
279 pub description: Option<String>,
280}
281
282#[derive(Debug, Serialize, Deserialize)]
283pub struct SetDefaultSpaceRequest {
284 pub space_id: String,
285}
286
287#[doc(hidden)]
290#[derive(Debug, Serialize, Deserialize)]
291pub struct CreateConceptRequest {
292 pub title: String,
293 pub content: String,
294 #[serde(default)]
295 pub summary: Option<String>,
296 #[serde(default)]
297 pub entity_id: Option<String>,
298 #[serde(
299 default,
300 alias = "domain",
301 skip_serializing_if = "WriteSpaceTarget::is_inherit"
302 )]
303 pub space: WriteSpaceTarget,
304 #[serde(default)]
305 pub source_memory_ids: Vec<String>,
306 #[serde(default)]
307 pub creation_kind: Option<String>,
308 #[serde(default)]
313 pub workspace: Option<String>,
314}
315
316#[derive(Debug, Clone, PartialEq, Eq)]
322pub struct CreatePageDraftRequest {
323 pub draft_id: String,
325 pub title: String,
326 pub content: String,
327 pub space: Option<String>,
328 space_provided: bool,
329}
330
331impl CreatePageDraftRequest {
332 pub fn new(draft_id: String, title: String, content: String, space: Option<String>) -> Self {
336 Self {
337 draft_id,
338 title,
339 content,
340 space,
341 space_provided: true,
342 }
343 }
344
345 pub fn new_inheriting_header_space(draft_id: String, title: String, content: String) -> Self {
348 Self {
349 draft_id,
350 title,
351 content,
352 space: None,
353 space_provided: false,
354 }
355 }
356
357 pub fn space_was_provided(&self) -> bool {
362 self.space_provided
363 }
364}
365
366impl Serialize for CreatePageDraftRequest {
367 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
368 where
369 S: serde::Serializer,
370 {
371 use serde::ser::SerializeStruct;
372
373 let field_count = if self.space_provided { 4 } else { 3 };
374 let mut state = serializer.serialize_struct("CreatePageDraftRequest", field_count)?;
375 state.serialize_field("draft_id", &self.draft_id)?;
376 state.serialize_field("title", &self.title)?;
377 state.serialize_field("content", &self.content)?;
378 if self.space_provided {
379 state.serialize_field("space", &self.space)?;
380 }
381 state.end()
382 }
383}
384
385impl<'de> Deserialize<'de> for CreatePageDraftRequest {
386 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
387 where
388 D: serde::Deserializer<'de>,
389 {
390 #[derive(Deserialize)]
391 struct Wire {
392 draft_id: String,
393 #[serde(default)]
394 title: String,
395 #[serde(default)]
396 content: String,
397 #[serde(default, deserialize_with = "double_option")]
398 space: Option<Option<String>>,
399 }
400
401 let wire = Wire::deserialize(deserializer)?;
402 let (space_provided, space) = match wire.space {
403 Some(space) => (true, space),
404 None => (false, None),
405 };
406 Ok(Self {
407 draft_id: wire.draft_id,
408 title: wire.title,
409 content: wire.content,
410 space,
411 space_provided,
412 })
413 }
414}
415
416#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
418pub struct UpdatePageDraftRequest {
419 pub expected_version: i64,
420 pub title: String,
421 pub content: String,
422 pub space: Option<String>,
423}
424
425impl<'de> Deserialize<'de> for UpdatePageDraftRequest {
426 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
427 where
428 D: serde::Deserializer<'de>,
429 {
430 #[derive(Deserialize)]
431 struct Wire {
432 expected_version: i64,
433 title: String,
434 content: String,
435 #[serde(default, deserialize_with = "double_option")]
436 space: Option<Option<String>>,
437 }
438
439 let wire = Wire::deserialize(deserializer)?;
440 let space = wire
441 .space
442 .ok_or_else(|| serde::de::Error::missing_field("space"))?;
443 Ok(Self {
444 expected_version: wire.expected_version,
445 title: wire.title,
446 content: wire.content,
447 space,
448 })
449 }
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
454pub struct PageDraftVersionRequest {
455 pub expected_version: i64,
456}
457
458#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
459#[serde(tag = "action", rename_all = "snake_case")]
460pub enum AcceptRefinementRequest {
461 Accept {
462 #[serde(default, skip_serializing_if = "Option::is_none")]
463 notes: Option<String>,
464 },
465 PickSpace {
466 space: String,
467 #[serde(default, skip_serializing_if = "Option::is_none")]
468 notes: Option<String>,
469 },
470}
471
472#[derive(Debug, Serialize, Deserialize)]
473pub struct SearchPagesRequest {
474 pub query: String,
475 #[serde(default)]
476 pub limit: Option<usize>,
477 #[serde(default, skip_serializing_if = "Option::is_none")]
478 pub page_type: Option<String>,
479 #[serde(default, skip_serializing_if = "Option::is_none")]
480 pub space: Option<String>,
481}
482
483#[derive(Debug, Serialize, Deserialize)]
486pub struct IngestTextRequest {
487 pub source: String,
488 pub source_id: String,
489 pub title: String,
490 pub content: String,
491 pub url: Option<String>,
492 pub metadata: Option<HashMap<String, String>>,
493}
494
495#[doc(hidden)]
496#[derive(Debug, Serialize, Deserialize)]
497pub struct IngestWebpageRequest {
498 pub url: String,
499 pub title: String,
500 pub content: String,
501 pub metadata: Option<HashMap<String, String>>,
502}
503
504#[derive(Debug, Serialize, Deserialize)]
505pub struct IngestMemoryRequest {
506 pub source: String,
507 pub source_id: String,
508 pub title: String,
509 pub content: String,
510 pub url: Option<String>,
511 pub tags: Option<Vec<String>>,
512 pub metadata: Option<HashMap<String, String>>,
513}
514
515#[doc(hidden)]
518#[derive(Debug, Serialize, Deserialize)]
519pub struct AddSourceRequest {
520 pub source_type: String,
521 pub path: String,
524}
525
526fn double_option<'de, T, D>(de: D) -> Result<Option<Option<T>>, D::Error>
531where
532 T: serde::Deserialize<'de>,
533 D: serde::Deserializer<'de>,
534{
535 serde::Deserialize::deserialize(de).map(Some)
536}
537
538#[derive(Debug, Serialize, Deserialize)]
539pub struct UpdateConfigRequest {
540 #[serde(default)]
541 pub skip_apps: Option<Vec<String>>,
542 #[serde(default)]
543 pub skip_title_patterns: Option<Vec<String>>,
544 #[serde(default)]
545 pub private_browsing_detection: Option<bool>,
546 #[serde(default)]
547 pub setup_completed: Option<bool>,
548 #[serde(default)]
549 pub clipboard_enabled: Option<bool>,
550 #[serde(default)]
551 pub screen_capture_enabled: Option<bool>,
552 #[serde(default)]
553 pub remote_access_enabled: Option<bool>,
554 #[serde(default)]
556 pub routine_model: Option<String>,
557 #[serde(default)]
559 pub synthesis_model: Option<String>,
560 #[serde(default)]
562 pub external_llm_endpoint: Option<String>,
563 #[serde(default)]
565 pub external_llm_model: Option<String>,
566 #[serde(
569 default,
570 deserialize_with = "double_option",
571 skip_serializing_if = "Option::is_none"
572 )]
573 pub external_llm_api_key: Option<Option<String>>,
574 #[serde(default)]
578 pub everyday_source: Option<String>,
579 #[serde(default)]
583 pub synthesis_source: Option<String>,
584 #[serde(default)]
587 pub page_map_auto_suggest: Option<bool>,
588}
589
590#[derive(Debug, Serialize, Deserialize)]
593pub struct DeleteByTimeRangeRequest {
594 pub start: i64,
595 pub end: i64,
596}
597
598#[derive(Debug, Serialize, Deserialize)]
599pub struct BulkDeleteItem {
600 pub source: String,
601 pub source_id: String,
602}
603
604#[derive(Debug, Serialize, Deserialize)]
605pub struct BulkDeleteRequest {
606 pub items: Vec<BulkDeleteItem>,
607}
608
609#[derive(Debug, Serialize, Deserialize)]
610pub struct UpdateChunkRequest {
611 pub content: String,
612}
613
614#[derive(Debug, Serialize, Deserialize)]
617pub struct ConfirmEntityRequest {
618 #[serde(default = "default_confirmed")]
619 pub confirmed: bool,
620}
621
622#[derive(Debug, Serialize, Deserialize)]
623pub struct AddEntityObservationRequest {
624 pub content: String,
625 #[serde(default)]
626 pub source_agent: Option<String>,
627 #[serde(default)]
628 pub confidence: Option<f32>,
629}
630
631#[derive(Debug, Serialize, Deserialize)]
632pub struct UpdateObservationRequest {
633 pub content: String,
634}
635
636#[derive(Debug, Serialize, Deserialize)]
637pub struct ConfirmObservationRequest {
638 #[serde(default = "default_confirmed")]
639 pub confirmed: bool,
640}
641
642#[derive(Debug, Serialize, Deserialize)]
645pub struct ReorderSpaceRequest {
646 pub name: String,
647 pub new_order: i64,
648}
649
650#[derive(Debug, Serialize, Deserialize)]
651pub struct SetDocumentSpaceRequest {
652 pub space_name: String,
653}
654
655#[derive(Debug, Serialize, Deserialize)]
658pub struct SetDocumentTagsRequest {
659 #[serde(default)]
660 pub source: Option<String>,
661 pub tags: Vec<String>,
662}
663
664#[derive(Debug, Serialize, Deserialize)]
667pub struct UpdateMemoryRequest {
668 #[serde(default)]
669 pub content: Option<String>,
670 #[serde(default, alias = "domain")]
671 pub space: Option<String>,
672 #[serde(default)]
673 pub confirmed: Option<bool>,
674 #[serde(default)]
675 pub memory_type: Option<String>,
676}
677
678#[derive(Debug, Serialize, Deserialize)]
679pub struct SetStabilityRequest {
680 pub stability: String,
681}
682
683#[derive(Debug, Serialize, Deserialize)]
684pub struct CorrectMemoryRequest {
685 pub correction_prompt: String,
686}
687
688#[derive(Debug, Serialize, Deserialize)]
691pub struct UpdatePageRequest {
692 pub content: String,
693 #[serde(default)]
697 pub source_memory_ids: Vec<String>,
698 #[serde(default)]
706 pub expected_version: Option<i64>,
707 #[serde(default)]
716 pub caller_id: Option<String>,
717 #[serde(default)]
718 pub operation_id: Option<String>,
719}
720
721#[derive(Debug, Serialize, Deserialize)]
731pub struct RefreshPageRequest {
732 pub content: String,
733 pub source_memory_ids: Vec<String>,
734 #[serde(default)]
735 pub summary: Option<String>,
736}
737
738#[derive(Debug, Deserialize, Serialize)]
742pub struct ExportPagesRequest {
743 pub vault_path: Option<String>,
744}
745
746#[derive(Debug, Deserialize, Serialize)]
747pub struct ExportPageRequest {
748 pub vault_path: String,
749}
750
751#[derive(Debug, Clone, Serialize, Deserialize)]
756pub struct TestLlmRequest {
757 pub endpoint: String,
758 pub model: String,
759 #[serde(default, skip_serializing_if = "Option::is_none")]
761 pub prompt: Option<String>,
762 #[serde(default, skip_serializing_if = "Option::is_none")]
764 pub api_key: Option<String>,
765}
766
767#[derive(Debug, Clone, Serialize, Deserialize)]
768pub struct TestLlmResponse {
769 pub response: String,
770}
771
772#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
776pub struct OnDeviceModelRequest {
777 pub model_id: String,
778}
779
780fn default_limit() -> usize {
783 10
784}
785
786fn default_list_limit() -> usize {
787 100
788}
789
790fn default_confirmed() -> bool {
791 true
792}
793
794fn default_max_chunks() -> usize {
795 5
796}
797
798pub(crate) fn default_true() -> bool {
799 true
800}
801
802fn default_entity_search_limit() -> usize {
803 20
804}
805
806#[cfg(test)]
807mod search_pages_page_type_test {
808 use super::*;
809
810 #[test]
811 fn search_pages_request_accepts_page_type() {
812 let json = r#"{"query":"foo","limit":10,"page_type":"recap"}"#;
813 let parsed: SearchPagesRequest = serde_json::from_str(json).unwrap();
814 assert_eq!(parsed.page_type.as_deref(), Some("recap"));
815 }
816
817 #[test]
818 fn search_pages_request_page_type_optional() {
819 let json = r#"{"query":"foo","limit":10}"#;
820 let parsed: SearchPagesRequest = serde_json::from_str(json).unwrap();
821 assert!(parsed.page_type.is_none());
822 }
823
824 #[test]
825 fn search_pages_request_accepts_optional_space() {
826 let json = r#"{"query":"foo","space":"work"}"#;
827 let parsed: SearchPagesRequest = serde_json::from_str(json).unwrap();
828 assert_eq!(parsed.space.as_deref(), Some("work"));
829
830 let omitted: SearchPagesRequest = serde_json::from_str(r#"{"query":"foo"}"#).unwrap();
831 assert!(omitted.space.is_none());
832 }
833}
834
835#[cfg(test)]
836mod list_memories_confirmed_test {
837 use super::*;
838
839 #[test]
840 fn confirmed_false_serializes_to_json() {
841 let req = ListMemoriesRequest {
842 memory_type: None,
843 space: None,
844 limit: 20,
845 confirmed: Some(false),
846 };
847 let s = serde_json::to_string(&req).unwrap();
848 assert!(s.contains("\"confirmed\":false"), "got: {s}");
849 }
850
851 #[test]
852 fn confirmed_none_skips_serialization() {
853 let req = ListMemoriesRequest {
854 memory_type: None,
855 space: None,
856 limit: 20,
857 confirmed: None,
858 };
859 let s = serde_json::to_string(&req).unwrap();
860 assert!(!s.contains("confirmed"), "got: {s}");
861 }
862}
863
864#[cfg(test)]
865mod set_document_tags_test {
866 use super::*;
867
868 #[test]
869 fn set_document_tags_request_accepts_optional_source() {
870 let req: SetDocumentTagsRequest =
871 serde_json::from_str(r#"{"source":"manual","tags":["rust"]}"#).unwrap();
872
873 assert_eq!(req.source.as_deref(), Some("manual"));
874 assert_eq!(req.tags, vec!["rust"]);
875 }
876
877 #[test]
878 fn set_document_tags_request_defaults_source_for_old_payloads() {
879 let req: SetDocumentTagsRequest = serde_json::from_str(r#"{"tags":["rust"]}"#).unwrap();
880
881 assert!(req.source.is_none());
882 assert_eq!(req.tags, vec!["rust"]);
883 }
884}
885
886#[cfg(test)]
887mod on_device_model_request_test {
888 use super::*;
889
890 #[test]
891 fn on_device_model_request_round_trips_model_id() {
892 let req: OnDeviceModelRequest = serde_json::from_str(r#"{"model_id":"qwen3-4b"}"#).unwrap();
893
894 assert_eq!(req.model_id, "qwen3-4b");
895 assert_eq!(
896 serde_json::to_string(&req).unwrap(),
897 r#"{"model_id":"qwen3-4b"}"#
898 );
899 }
900}
901
902#[cfg(test)]
903mod tests {
904 use super::*;
905
906 #[test]
907 fn update_config_request_external_key_tristate() {
908 let r: UpdateConfigRequest = serde_json::from_str("{}").unwrap();
909 assert_eq!(r.external_llm_api_key, None); let r: UpdateConfigRequest =
911 serde_json::from_str(r#"{"external_llm_api_key":null}"#).unwrap();
912 assert_eq!(r.external_llm_api_key, Some(None)); let r: UpdateConfigRequest =
914 serde_json::from_str(r#"{"external_llm_api_key":"sk-x"}"#).unwrap();
915 assert_eq!(r.external_llm_api_key, Some(Some("sk-x".to_string())));
916 }
917
918 #[test]
919 fn test_llm_request_api_key_optional() {
920 let r: TestLlmRequest =
921 serde_json::from_str(r#"{"endpoint":"http://x","model":"m"}"#).unwrap();
922 assert!(r.api_key.is_none());
923 }
924}
925
926#[derive(Clone, Deserialize)]
942pub struct PresenceCapability {
943 pub protocol_version: u32,
944 pub action: String,
948 pub target_ids: Vec<String>,
949 pub base_digest: String,
951 pub caller_id: String,
952 pub operation_id: String,
953 pub minted_at: u64,
954 pub expires_at: u64,
955 pub nonce: String,
956 pub mac: String,
957}
958
959impl std::fmt::Debug for PresenceCapability {
962 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
963 f.debug_struct("PresenceCapability")
964 .field("protocol_version", &self.protocol_version)
965 .field("action", &self.action)
966 .field("target_ids", &self.target_ids)
967 .field("base_digest", &self.base_digest)
968 .field("caller_id", &self.caller_id)
969 .field("operation_id", &self.operation_id)
970 .field("minted_at", &self.minted_at)
971 .field("expires_at", &self.expires_at)
972 .field("nonce", &"<redacted>")
973 .field("mac", &"<redacted>")
974 .finish()
975 }
976}
977
978#[derive(Debug, Clone, Deserialize)]
985pub struct ReviewPageRequest {
986 pub presence: PresenceCapability,
987}