agent_sdk_core/domain/refs.rs
1//! Domain primitives for stable SDK vocabulary. Use these items for IDs, refs,
2//! policy, privacy, trust, and errors that cross crate or host boundaries. They are
3//! data-only and must not perform provider, filesystem, network, or UI side effects.
4//! This file contains the refs portion of that contract.
5//!
6use core::fmt;
7use serde::{Deserialize, Deserializer, Serialize, de::Error as DeError};
8
9use crate::ids::{
10 AgentId, AgentPoolId, ApprovalRequestId, ArtifactId, AttemptId, ContextItemId,
11 ContextProjectionId, CorrelationEntry, EffectId, EventId, IdValidationError, LineageId,
12 MessageId, RunId, RuntimePackageId, ToolCallId, TopicId, TurnId, WakeConditionId,
13 validate_identifier,
14};
15use crate::privacy::{PrivacyClass, RetentionClass, TrustClass};
16
17#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
18#[serde(rename_all = "snake_case")]
19/// Enumerates the finite entity kind cases.
20/// Serialized names are part of the SDK contract; update fixtures when variants change.
21pub enum EntityKind {
22 /// Use this variant when the contract needs to represent run; selecting it has no side effect by itself.
23 Run,
24 /// Use this variant when the contract needs to represent turn; selecting it has no side effect by itself.
25 Turn,
26 /// Use this variant when the contract needs to represent attempt; selecting it has no side effect by itself.
27 Attempt,
28 /// Use this variant when the contract needs to represent agent; selecting it has no side effect by itself.
29 Agent,
30 /// Use this variant when the contract needs to represent agent pool; selecting it has no side effect by itself.
31 AgentPool,
32 /// Use this variant when the contract needs to represent topic; selecting it has no side effect by itself.
33 Topic,
34 /// Use this variant when the contract needs to represent event; selecting it has no side effect by itself.
35 Event,
36 /// Use this variant when the contract needs to represent message; selecting it has no side effect by itself.
37 Message,
38 /// Use this variant when the contract needs to represent wake condition; selecting it has no side effect by itself.
39 WakeCondition,
40 /// Use this variant when the contract needs to represent context contribution; selecting it has no side effect by itself.
41 ContextContribution,
42 /// Use this variant when the contract needs to represent context item; selecting it has no side effect by itself.
43 ContextItem,
44 /// Use this variant when the contract needs to represent context projection; selecting it has no side effect by itself.
45 ContextProjection,
46 /// Use this variant when the contract needs to represent content; selecting it has no side effect by itself.
47 Content,
48 /// Use this variant when the contract needs to represent artifact; selecting it has no side effect by itself.
49 Artifact,
50 /// Use this variant when the contract needs to represent capability; selecting it has no side effect by itself.
51 Capability,
52 /// Use this variant when the contract needs to represent package sidecar; selecting it has no side effect by itself.
53 PackageSidecar,
54 /// Use this variant when the contract needs to represent runtime package; selecting it has no side effect by itself.
55 RuntimePackage,
56 /// Use this variant when the contract needs to represent policy decision; selecting it has no side effect by itself.
57 PolicyDecision,
58 /// Use this variant when the contract needs to represent effect; selecting it has no side effect by itself.
59 Effect,
60 /// Use this variant when the contract needs to represent effect intent; selecting it has no side effect by itself.
61 EffectIntent,
62 /// Use this variant when the contract needs to represent effect result; selecting it has no side effect by itself.
63 EffectResult,
64 /// Use this variant when the contract needs to represent tool call; selecting it has no side effect by itself.
65 ToolCall,
66 /// Use this variant when the contract needs to represent approval request; selecting it has no side effect by itself.
67 ApprovalRequest,
68 /// Use this variant when the contract needs to represent stream rule; selecting it has no side effect by itself.
69 StreamRule,
70 /// Use this variant when the contract needs to represent realtime session; selecting it has no side effect by itself.
71 RealtimeSession,
72 /// Use this variant when the contract needs to represent hook; selecting it has no side effect by itself.
73 Hook,
74 /// Use this variant when the contract needs to represent execution environment; selecting it has no side effect by itself.
75 ExecutionEnvironment,
76 /// Use this variant when the contract needs to represent child artifact; selecting it has no side effect by itself.
77 ChildArtifact,
78 /// Use this variant when the contract needs to represent subagent run; selecting it has no side effect by itself.
79 SubagentRun,
80 /// Use this variant when the contract needs to represent extension action; selecting it has no side effect by itself.
81 ExtensionAction,
82 /// Use this variant when the contract needs to represent output delivery; selecting it has no side effect by itself.
83 OutputDelivery,
84}
85
86#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
87#[serde(transparent)]
88/// Defines the entity id SDK value.
89/// Construction records local state only; documented runtimes, executors, or ports own side effects.
90pub struct EntityId(String);
91
92impl EntityId {
93 /// Creates a new domain::refs value with explicit caller-provided
94 /// inputs. This constructor is data-only and performs no I/O or
95 /// external side effects.
96 ///
97 /// # Panics
98 ///
99 /// Panics if constructor invariants fail, such as invalid identifier
100 /// text or constructor-specific bounds. Use a fallible constructor such as
101 /// `try_new` when one is available for untrusted input.
102 pub fn new(value: impl Into<String>) -> Self {
103 Self::try_new(value).expect("EntityId must be valid")
104 }
105
106 /// Creates a new domain::refs value after validation. Returns an
107 /// SDK error instead of panicking when the identifier or input does
108 /// not satisfy the contract.
109 pub fn try_new(value: impl Into<String>) -> Result<Self, IdValidationError> {
110 let value = value.into();
111 validate_identifier(&value)?;
112 Ok(Self(value))
113 }
114
115 /// Returns this value as str. The accessor is side-effect free and
116 /// keeps ownership with the caller.
117 pub fn as_str(&self) -> &str {
118 &self.0
119 }
120}
121
122impl fmt::Debug for EntityId {
123 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
124 formatter.write_str("EntityId(redacted)")
125 }
126}
127
128impl fmt::Display for EntityId {
129 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
130 formatter.write_str("EntityId(redacted)")
131 }
132}
133
134impl From<&str> for EntityId {
135 fn from(value: &str) -> Self {
136 Self::try_new(value).expect("EntityId must be valid")
137 }
138}
139
140impl<'de> Deserialize<'de> for EntityId {
141 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
142 where
143 D: Deserializer<'de>,
144 {
145 let value = String::deserialize(deserializer)?;
146 Self::try_new(value).map_err(D::Error::custom)
147 }
148}
149
150impl From<RunId> for EntityId {
151 fn from(value: RunId) -> Self {
152 Self::new(value.as_str())
153 }
154}
155
156impl From<TurnId> for EntityId {
157 fn from(value: TurnId) -> Self {
158 Self::new(value.as_str())
159 }
160}
161
162impl From<AttemptId> for EntityId {
163 fn from(value: AttemptId) -> Self {
164 Self::new(value.as_str())
165 }
166}
167
168impl From<AgentId> for EntityId {
169 fn from(value: AgentId) -> Self {
170 Self::new(value.as_str())
171 }
172}
173
174impl From<AgentPoolId> for EntityId {
175 fn from(value: AgentPoolId) -> Self {
176 Self::new(value.as_str())
177 }
178}
179
180impl From<TopicId> for EntityId {
181 fn from(value: TopicId) -> Self {
182 Self::new(value.as_str())
183 }
184}
185
186impl From<EventId> for EntityId {
187 fn from(value: EventId) -> Self {
188 Self::new(value.as_str())
189 }
190}
191
192impl From<MessageId> for EntityId {
193 fn from(value: MessageId) -> Self {
194 Self::new(value.as_str())
195 }
196}
197
198impl From<WakeConditionId> for EntityId {
199 fn from(value: WakeConditionId) -> Self {
200 Self::new(value.as_str())
201 }
202}
203
204impl From<ContextItemId> for EntityId {
205 fn from(value: ContextItemId) -> Self {
206 Self::new(value.as_str())
207 }
208}
209
210impl From<ContextProjectionId> for EntityId {
211 fn from(value: ContextProjectionId) -> Self {
212 Self::new(value.as_str())
213 }
214}
215
216impl From<ArtifactId> for EntityId {
217 fn from(value: ArtifactId) -> Self {
218 Self::new(value.as_str())
219 }
220}
221
222impl From<RuntimePackageId> for EntityId {
223 fn from(value: RuntimePackageId) -> Self {
224 Self::new(value.as_str())
225 }
226}
227
228impl From<EffectId> for EntityId {
229 fn from(value: EffectId) -> Self {
230 Self::new(value.as_str())
231 }
232}
233
234impl From<ToolCallId> for EntityId {
235 fn from(value: ToolCallId) -> Self {
236 Self::new(value.as_str())
237 }
238}
239
240impl From<ApprovalRequestId> for EntityId {
241 fn from(value: ApprovalRequestId) -> Self {
242 Self::new(value.as_str())
243 }
244}
245
246#[derive(Clone, Deserialize, Eq, PartialEq, Serialize)]
247/// Defines the entity ref SDK value.
248/// Construction records local state only; documented runtimes, executors, or ports own side effects.
249pub struct EntityRef {
250 /// Kind/category for this record, capability, event, or detected
251 /// resource.
252 pub kind: EntityKind,
253 /// Stable identifier for this record.
254 pub id: EntityId,
255 #[serde(skip_serializing_if = "Option::is_none")]
256 /// Source label or ref for this item; it is metadata and does not fetch
257 /// content by itself.
258 pub source: Option<SourceRef>,
259 /// Privacy class used for projection, telemetry, and raw-content access
260 /// decisions.
261 pub privacy: PrivacyClass,
262 #[serde(skip_serializing_if = "Option::is_none")]
263 /// Redacted human-readable summary safe for events, telemetry, and logs.
264 pub redacted_summary: Option<String>,
265}
266
267impl EntityRef {
268 /// Creates a new domain::refs value with explicit caller-provided
269 /// inputs. This constructor is data-only and performs no I/O or
270 /// external side effects.
271 pub fn new(kind: EntityKind, id: impl Into<EntityId>) -> Self {
272 Self {
273 kind,
274 id: id.into(),
275 source: None,
276 privacy: PrivacyClass::ContentRefsOnly,
277 redacted_summary: None,
278 }
279 }
280
281 /// Builds the run value with the documented defaults.
282 /// This is data-only and does not perform I/O, call host ports, append journals, publish
283 /// events, or start processes.
284 pub fn run(id: RunId) -> Self {
285 Self::new(EntityKind::Run, id)
286 }
287
288 /// Returns agent for the current value.
289 /// This is a read-only or data-construction helper unless the method body explicitly calls
290 /// a port or store.
291 pub fn agent(id: AgentId) -> Self {
292 Self::new(EntityKind::Agent, id)
293 }
294
295 /// Builds the agent pool value.
296 /// This is data construction and performs no I/O, journal append, event publication, or
297 /// process work.
298 pub fn agent_pool(id: AgentPoolId) -> Self {
299 Self::new(EntityKind::AgentPool, id)
300 }
301
302 /// Returns an updated value with topic configured.
303 /// This is data-only and does not perform I/O, call host ports, append journals, publish
304 /// events, or start processes.
305 pub fn topic(id: TopicId) -> Self {
306 Self::new(EntityKind::Topic, id)
307 }
308
309 /// Builds the message value.
310 /// This is data construction and performs no I/O, journal append, event publication, or
311 /// process work.
312 pub fn message(id: MessageId) -> Self {
313 Self::new(EntityKind::Message, id)
314 }
315
316 /// Builds the wake condition value.
317 /// This is data construction and performs no I/O, journal append, event publication, or
318 /// process work.
319 pub fn wake_condition(id: WakeConditionId) -> Self {
320 Self::new(EntityKind::WakeCondition, id)
321 }
322
323 /// Returns this value as str. The accessor is side-effect free and
324 /// keeps ownership with the caller.
325 pub fn as_str(&self) -> &str {
326 self.id.as_str()
327 }
328}
329
330impl fmt::Debug for EntityRef {
331 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
332 formatter
333 .debug_struct("EntityRef")
334 .field("kind", &self.kind)
335 .field("id", &"redacted")
336 .field("source", &self.source)
337 .field("privacy", &self.privacy)
338 .field("redacted_summary", &self.redacted_summary)
339 .finish()
340 }
341}
342
343impl fmt::Display for EntityRef {
344 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
345 write!(formatter, "{:?}:redacted", self.kind)
346 }
347}
348
349#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
350#[serde(rename_all = "snake_case")]
351/// Enumerates the finite source kind cases.
352/// Serialized names are part of the SDK contract; update fixtures when variants change.
353pub enum SourceKind {
354 /// Use this variant when the contract needs to represent sdk; selecting it has no side effect by itself.
355 Sdk,
356 /// Use this variant when the contract needs to represent host; selecting it has no side effect by itself.
357 Host,
358 /// Use this variant when the contract needs to represent user; selecting it has no side effect by itself.
359 User,
360 /// Use this variant when the contract needs to represent system; selecting it has no side effect by itself.
361 System,
362 /// Use this variant when the contract needs to represent developer; selecting it has no side effect by itself.
363 Developer,
364 /// Use this variant when the contract needs to represent memory; selecting it has no side effect by itself.
365 Memory,
366 /// Use this variant when the contract needs to represent compaction; selecting it has no side effect by itself.
367 Compaction,
368 /// Use this variant when the contract needs to represent hook; selecting it has no side effect by itself.
369 Hook,
370 /// Use this variant when the contract needs to represent extension; selecting it has no side effect by itself.
371 Extension,
372 /// Use this variant when the contract needs to represent tool; selecting it has no side effect by itself.
373 Tool,
374 /// Use this variant when the contract needs to represent remote channel; selecting it has no side effect by itself.
375 RemoteChannel,
376 /// Use this variant when the contract needs to represent scheduled task; selecting it has no side effect by itself.
377 ScheduledTask,
378 /// Use this variant when the contract needs to represent subagent; selecting it has no side effect by itself.
379 Subagent,
380 /// Use this variant when the contract needs to represent external runtime; selecting it has no side effect by itself.
381 ExternalRuntime,
382 /// Use this variant when the contract needs to represent replay; selecting it has no side effect by itself.
383 Replay,
384}
385
386#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
387#[serde(transparent)]
388/// Defines the source id SDK value.
389/// Construction records local state only; documented runtimes, executors, or ports own side effects.
390pub struct SourceId(String);
391
392impl SourceId {
393 /// Creates a new domain::refs value with explicit caller-provided
394 /// inputs. This constructor is data-only and performs no I/O or
395 /// external side effects.
396 ///
397 /// # Panics
398 ///
399 /// Panics if constructor invariants fail, such as invalid identifier
400 /// text or constructor-specific bounds. Use a fallible constructor such as
401 /// `try_new` when one is available for untrusted input.
402 pub fn new(value: impl Into<String>) -> Self {
403 Self::try_new(value).expect("SourceId must be valid")
404 }
405
406 /// Creates a new domain::refs value after validation. Returns an
407 /// SDK error instead of panicking when the identifier or input does
408 /// not satisfy the contract.
409 pub fn try_new(value: impl Into<String>) -> Result<Self, IdValidationError> {
410 let value = value.into();
411 validate_identifier(&value)?;
412 Ok(Self(value))
413 }
414
415 /// Returns this value as str. The accessor is side-effect free and
416 /// keeps ownership with the caller.
417 pub fn as_str(&self) -> &str {
418 &self.0
419 }
420}
421
422impl<'de> Deserialize<'de> for SourceId {
423 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
424 where
425 D: Deserializer<'de>,
426 {
427 let value = String::deserialize(deserializer)?;
428 Self::try_new(value).map_err(D::Error::custom)
429 }
430}
431
432impl fmt::Debug for SourceId {
433 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
434 formatter.write_str("SourceId(redacted)")
435 }
436}
437
438impl fmt::Display for SourceId {
439 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
440 formatter.write_str("SourceId(redacted)")
441 }
442}
443
444#[derive(Clone, Deserialize, Eq, PartialEq, Serialize)]
445/// Defines the source ref SDK value.
446/// Construction records local state only; documented runtimes, executors, or ports own side effects.
447pub struct SourceRef {
448 /// Kind/category for this record, capability, event, or detected
449 /// resource.
450 pub kind: SourceKind,
451 /// Stable identifier for this record.
452 pub id: SourceId,
453 /// Trust class used when deciding whether context or capabilities may be
454 /// admitted.
455 pub trust: TrustClass,
456 /// Privacy class used for projection, telemetry, and raw-content access
457 /// decisions.
458 pub privacy: PrivacyClass,
459 #[serde(default, skip_serializing_if = "Vec::is_empty")]
460 /// Collection of correlation values.
461 /// Ordering and membership should be treated as part of the serialized contract when
462 /// relevant.
463 pub correlation: Vec<CorrelationEntry>,
464 #[serde(skip_serializing_if = "Option::is_none")]
465 /// Redacted human-readable summary safe for events, telemetry, and logs.
466 pub redacted_summary: Option<String>,
467}
468
469impl SourceRef {
470 /// Creates a new domain::refs value with explicit caller-provided
471 /// inputs. This constructor is data-only and performs no I/O or
472 /// external side effects.
473 pub fn new(id: impl Into<String>) -> Self {
474 Self::with_kind(SourceKind::Host, id)
475 }
476
477 /// Returns this value with its kind setting replaced. The method
478 /// follows builder-style data construction and does not execute
479 /// external work.
480 pub fn with_kind(kind: SourceKind, id: impl Into<String>) -> Self {
481 Self {
482 kind,
483 id: SourceId::new(id),
484 trust: TrustClass::HostProvided,
485 privacy: PrivacyClass::ContentRefsOnly,
486 correlation: Vec::new(),
487 redacted_summary: None,
488 }
489 }
490
491 /// Returns this value as str. The accessor is side-effect free and
492 /// keeps ownership with the caller.
493 pub fn as_str(&self) -> &str {
494 self.id.as_str()
495 }
496}
497
498impl fmt::Debug for SourceRef {
499 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
500 formatter
501 .debug_struct("SourceRef")
502 .field("kind", &self.kind)
503 .field("id", &"redacted")
504 .field("trust", &self.trust)
505 .field("privacy", &self.privacy)
506 .field("correlation", &self.correlation)
507 .field("redacted_summary", &self.redacted_summary)
508 .finish()
509 }
510}
511
512impl fmt::Display for SourceRef {
513 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
514 write!(formatter, "{:?}:redacted", self.kind)
515 }
516}
517
518#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
519#[serde(rename_all = "snake_case")]
520/// Enumerates the finite destination kind cases.
521/// Serialized names are part of the SDK contract; update fixtures when variants change.
522pub enum DestinationKind {
523 /// Use this variant when the contract needs to represent agent; selecting it has no side effect by itself.
524 Agent,
525 /// Use this variant when the contract needs to represent agent pool; selecting it has no side effect by itself.
526 AgentPool,
527 /// Use this variant when the contract needs to represent topic; selecting it has no side effect by itself.
528 Topic,
529 /// Use this variant when the contract needs to represent provider; selecting it has no side effect by itself.
530 Provider,
531 /// Use this variant when the contract needs to represent context projection; selecting it has no side effect by itself.
532 ContextProjection,
533 /// Use this variant when the contract needs to represent journal; selecting it has no side effect by itself.
534 Journal,
535 /// Use this variant when the contract needs to represent event stream; selecting it has no side effect by itself.
536 EventStream,
537 /// Use this variant when the contract needs to represent telemetry; selecting it has no side effect by itself.
538 Telemetry,
539 /// Use this variant when the contract needs to represent output sink; selecting it has no side effect by itself.
540 OutputSink,
541 /// Use this variant when the contract needs to represent host; selecting it has no side effect by itself.
542 Host,
543 /// Use this variant when the contract needs to represent user; selecting it has no side effect by itself.
544 User,
545 /// Use this variant when the contract needs to represent remote channel; selecting it has no side effect by itself.
546 RemoteChannel,
547 /// Use this variant when the contract needs to represent tool; selecting it has no side effect by itself.
548 Tool,
549 /// Use this variant when the contract needs to represent extension; selecting it has no side effect by itself.
550 Extension,
551 /// Use this variant when the contract needs to represent subagent; selecting it has no side effect by itself.
552 Subagent,
553 /// Use this variant when the contract needs to represent external runtime; selecting it has no side effect by itself.
554 ExternalRuntime,
555}
556
557#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
558#[serde(transparent)]
559/// Defines the destination id SDK value.
560/// Construction records local state only; documented runtimes, executors, or ports own side effects.
561pub struct DestinationId(String);
562
563impl DestinationId {
564 /// Creates a new domain::refs value with explicit caller-provided
565 /// inputs. This constructor is data-only and performs no I/O or
566 /// external side effects.
567 ///
568 /// # Panics
569 ///
570 /// Panics if constructor invariants fail, such as invalid identifier
571 /// text or constructor-specific bounds. Use a fallible constructor such as
572 /// `try_new` when one is available for untrusted input.
573 pub fn new(value: impl Into<String>) -> Self {
574 Self::try_new(value).expect("DestinationId must be valid")
575 }
576
577 /// Creates a new domain::refs value after validation. Returns an
578 /// SDK error instead of panicking when the identifier or input does
579 /// not satisfy the contract.
580 pub fn try_new(value: impl Into<String>) -> Result<Self, IdValidationError> {
581 let value = value.into();
582 validate_identifier(&value)?;
583 Ok(Self(value))
584 }
585
586 /// Returns this value as str. The accessor is side-effect free and
587 /// keeps ownership with the caller.
588 pub fn as_str(&self) -> &str {
589 &self.0
590 }
591}
592
593impl<'de> Deserialize<'de> for DestinationId {
594 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
595 where
596 D: Deserializer<'de>,
597 {
598 let value = String::deserialize(deserializer)?;
599 Self::try_new(value).map_err(D::Error::custom)
600 }
601}
602
603impl fmt::Debug for DestinationId {
604 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
605 formatter.write_str("DestinationId(redacted)")
606 }
607}
608
609impl fmt::Display for DestinationId {
610 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
611 formatter.write_str("DestinationId(redacted)")
612 }
613}
614
615#[derive(Clone, Deserialize, Eq, PartialEq, Serialize)]
616/// Defines the destination ref SDK value.
617/// Construction records local state only; documented runtimes, executors, or ports own side effects.
618pub struct DestinationRef {
619 /// Kind/category for this record, capability, event, or detected
620 /// resource.
621 pub kind: DestinationKind,
622 /// Stable identifier for this record.
623 pub id: DestinationId,
624 /// Privacy class used for projection, telemetry, and raw-content access
625 /// decisions.
626 pub privacy: PrivacyClass,
627 /// Retention class used by hosts and sinks when storing or exporting this
628 /// item.
629 pub retention: RetentionClass,
630 #[serde(default, skip_serializing_if = "Vec::is_empty")]
631 /// Collection of correlation values.
632 /// Ordering and membership should be treated as part of the serialized contract when
633 /// relevant.
634 pub correlation: Vec<CorrelationEntry>,
635 #[serde(skip_serializing_if = "Option::is_none")]
636 /// Redacted human-readable summary safe for events, telemetry, and logs.
637 pub redacted_summary: Option<String>,
638}
639
640impl DestinationRef {
641 /// Creates a new domain::refs value with explicit caller-provided
642 /// inputs. This constructor is data-only and performs no I/O or
643 /// external side effects.
644 pub fn new(id: impl Into<String>) -> Self {
645 Self::with_kind(DestinationKind::Host, id)
646 }
647
648 /// Returns this value with its kind setting replaced. The method
649 /// follows builder-style data construction and does not execute
650 /// external work.
651 pub fn with_kind(kind: DestinationKind, id: impl Into<String>) -> Self {
652 Self {
653 kind,
654 id: DestinationId::new(id),
655 privacy: PrivacyClass::ContentRefsOnly,
656 retention: RetentionClass::HostPolicy,
657 correlation: Vec::new(),
658 redacted_summary: None,
659 }
660 }
661
662 /// Returns this value as str. The accessor is side-effect free and
663 /// keeps ownership with the caller.
664 pub fn as_str(&self) -> &str {
665 self.id.as_str()
666 }
667}
668
669impl fmt::Debug for DestinationRef {
670 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
671 formatter
672 .debug_struct("DestinationRef")
673 .field("kind", &self.kind)
674 .field("id", &"redacted")
675 .field("privacy", &self.privacy)
676 .field("retention", &self.retention)
677 .field("correlation", &self.correlation)
678 .field("redacted_summary", &self.redacted_summary)
679 .finish()
680 }
681}
682
683impl fmt::Display for DestinationRef {
684 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
685 write!(formatter, "{:?}:redacted", self.kind)
686 }
687}
688
689#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
690#[serde(rename_all = "snake_case")]
691/// Enumerates the finite policy kind cases.
692/// Serialized names are part of the SDK contract; update fixtures when variants change.
693pub enum PolicyKind {
694 /// Use this variant when the contract needs to represent approval; selecting it has no side effect by itself.
695 Approval,
696 /// Use this variant when the contract needs to represent permission; selecting it has no side effect by itself.
697 Permission,
698 /// Use this variant when the contract needs to represent sandbox; selecting it has no side effect by itself.
699 Sandbox,
700 /// Use this variant when the contract needs to represent context; selecting it has no side effect by itself.
701 Context,
702 /// Use this variant when the contract needs to represent privacy; selecting it has no side effect by itself.
703 Privacy,
704 /// Use this variant when the contract needs to represent retention; selecting it has no side effect by itself.
705 Retention,
706 /// Use this variant when the contract needs to represent redaction; selecting it has no side effect by itself.
707 Redaction,
708 /// Use this variant when the contract needs to represent runtime package; selecting it has no side effect by itself.
709 RuntimePackage,
710 /// Use this variant when the contract needs to represent host; selecting it has no side effect by itself.
711 Host,
712}
713
714#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
715#[serde(transparent)]
716/// Defines the policy id SDK value.
717/// Construction records local state only; documented runtimes, executors, or ports own side effects.
718pub struct PolicyId(String);
719
720impl PolicyId {
721 /// Creates a new domain::refs value with explicit caller-provided
722 /// inputs. This constructor is data-only and performs no I/O or
723 /// external side effects.
724 ///
725 /// # Panics
726 ///
727 /// Panics if constructor invariants fail, such as invalid identifier
728 /// text or constructor-specific bounds. Use a fallible constructor such as
729 /// `try_new` when one is available for untrusted input.
730 pub fn new(value: impl Into<String>) -> Self {
731 Self::try_new(value).expect("PolicyId must be valid")
732 }
733
734 /// Creates a new domain::refs value after validation. Returns an
735 /// SDK error instead of panicking when the identifier or input does
736 /// not satisfy the contract.
737 pub fn try_new(value: impl Into<String>) -> Result<Self, IdValidationError> {
738 let value = value.into();
739 validate_identifier(&value)?;
740 Ok(Self(value))
741 }
742
743 /// Returns this value as str. The accessor is side-effect free and
744 /// keeps ownership with the caller.
745 pub fn as_str(&self) -> &str {
746 &self.0
747 }
748}
749
750impl<'de> Deserialize<'de> for PolicyId {
751 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
752 where
753 D: Deserializer<'de>,
754 {
755 let value = String::deserialize(deserializer)?;
756 Self::try_new(value).map_err(D::Error::custom)
757 }
758}
759
760#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
761#[serde(transparent)]
762/// Defines the adapter ref SDK value.
763/// Construction records local state only; documented runtimes, executors, or ports own side effects.
764pub struct AdapterRef(String);
765
766impl AdapterRef {
767 /// Creates a new domain::refs value with explicit caller-provided
768 /// inputs. This constructor is data-only and performs no I/O or
769 /// external side effects.
770 ///
771 /// # Panics
772 ///
773 /// Panics if constructor invariants fail, such as invalid identifier
774 /// text or constructor-specific bounds. Use a fallible constructor such as
775 /// `try_new` when one is available for untrusted input.
776 pub fn new(value: impl Into<String>) -> Self {
777 Self::try_new(value).expect("AdapterRef must be valid")
778 }
779
780 /// Creates a new domain::refs value after validation. Returns an
781 /// SDK error instead of panicking when the identifier or input does
782 /// not satisfy the contract.
783 pub fn try_new(value: impl Into<String>) -> Result<Self, IdValidationError> {
784 let value = value.into();
785 validate_identifier(&value)?;
786 Ok(Self(value))
787 }
788
789 /// Returns this value as str. The accessor is side-effect free and
790 /// keeps ownership with the caller.
791 pub fn as_str(&self) -> &str {
792 &self.0
793 }
794}
795
796impl fmt::Debug for AdapterRef {
797 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
798 formatter.write_str("AdapterRef(redacted)")
799 }
800}
801
802impl fmt::Display for AdapterRef {
803 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
804 formatter.write_str("AdapterRef(redacted)")
805 }
806}
807
808impl From<&str> for AdapterRef {
809 fn from(value: &str) -> Self {
810 Self::new(value)
811 }
812}
813
814impl<'de> Deserialize<'de> for AdapterRef {
815 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
816 where
817 D: Deserializer<'de>,
818 {
819 let value = String::deserialize(deserializer)?;
820 Self::try_new(value).map_err(D::Error::custom)
821 }
822}
823
824impl fmt::Debug for PolicyId {
825 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
826 formatter.write_str("PolicyId(redacted)")
827 }
828}
829
830impl fmt::Display for PolicyId {
831 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
832 formatter.write_str("PolicyId(redacted)")
833 }
834}
835
836#[derive(Clone, Deserialize, Eq, PartialEq, Serialize)]
837/// Defines the policy ref SDK value.
838/// Construction records local state only; documented runtimes, executors, or ports own side effects.
839pub struct PolicyRef {
840 /// Kind/category for this record, capability, event, or detected
841 /// resource.
842 pub kind: PolicyKind,
843 /// Stable identifier for this record.
844 pub id: PolicyId,
845 #[serde(skip_serializing_if = "Option::is_none")]
846 /// Version string for this capability, package, or protocol surface.
847 /// Use it for compatibility checks during package or adapter resolution.
848 pub version: Option<String>,
849}
850
851impl PolicyRef {
852 /// Creates a new domain::refs value with explicit caller-provided
853 /// inputs. This constructor is data-only and performs no I/O or
854 /// external side effects.
855 pub fn new(id: impl Into<String>) -> Self {
856 Self::with_kind(PolicyKind::Host, id)
857 }
858
859 /// Returns this value with its kind setting replaced. The method
860 /// follows builder-style data construction and does not execute
861 /// external work.
862 pub fn with_kind(kind: PolicyKind, id: impl Into<String>) -> Self {
863 Self {
864 kind,
865 id: PolicyId::new(id),
866 version: None,
867 }
868 }
869
870 /// Returns this value as str. The accessor is side-effect free and
871 /// keeps ownership with the caller.
872 pub fn as_str(&self) -> &str {
873 self.id.as_str()
874 }
875}
876
877impl fmt::Debug for PolicyRef {
878 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
879 formatter
880 .debug_struct("PolicyRef")
881 .field("kind", &self.kind)
882 .field("id", &"redacted")
883 .field("version", &self.version)
884 .finish()
885 }
886}
887
888impl fmt::Display for PolicyRef {
889 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
890 write!(formatter, "{:?}:redacted", self.kind)
891 }
892}
893
894#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
895/// Defines the lineage ref SDK value.
896/// Construction records local state only; documented runtimes, executors, or ports own side effects.
897pub struct LineageRef {
898 /// Stable lineage id used for typed lineage, lookup, or dedupe.
899 pub lineage_id: LineageId,
900 /// Source label or ref for this item; it is metadata and does not fetch
901 /// content by itself.
902 pub source: SourceRef,
903 #[serde(skip_serializing_if = "Option::is_none")]
904 /// Destination label or ref for this item; it is metadata and does not
905 /// deliver content by itself.
906 pub destination: Option<DestinationRef>,
907 #[serde(default, skip_serializing_if = "Vec::is_empty")]
908 /// Policy references that govern admission, projection, execution, or
909 /// delivery.
910 pub policy_refs: Vec<PolicyRef>,
911}