Skip to main content

loong_contracts/
lib.rs

1#![forbid(unsafe_code)]
2
3mod audit_types;
4mod child_process_env;
5mod clock;
6mod contracts;
7mod errors;
8mod execution_security_types;
9mod fault;
10mod memory_types;
11mod namespace;
12mod pack;
13mod policy_types;
14mod runtime_types;
15mod secret_ref;
16mod secret_resolver;
17mod secret_value;
18mod task_state;
19mod tool_types;
20mod work_types;
21mod workflow_types;
22
23pub use audit_types::{AuditEvent, AuditEventKind, ExecutionPlane, PlaneTier};
24pub use child_process_env::{
25    HIGH_RISK_CHILD_PROCESS_ENV_VARS, child_process_env_var_is_allowed, sanitized_child_process_env,
26};
27pub use clock::{Clock, FixedClock, SystemClock};
28pub use contracts::{
29    Capability, CapabilityToken, ConnectorCommand, ConnectorOutcome, ExecutionRoute, HarnessKind,
30    HarnessOutcome, HarnessRequest, TaskIntent,
31};
32pub use errors::{
33    AuditError, ConnectorError, HarnessError, IntegrationError, KernelError, MemoryPlaneError,
34    PackError, PolicyError, RuntimePlaneError, ToolPlaneError,
35};
36pub use execution_security_types::ExecutionSecurityTier;
37pub use fault::Fault;
38pub use memory_types::{
39    MemoryCoreOutcome, MemoryCoreRequest, MemoryExtensionOutcome, MemoryExtensionRequest,
40    MemoryTier,
41};
42pub use namespace::Namespace;
43pub use pack::VerticalPackManifest;
44pub use policy_types::{PolicyContext, PolicyDecision, PolicyRequest};
45pub use runtime_types::{
46    RuntimeCoreOutcome, RuntimeCoreRequest, RuntimeExtensionOutcome, RuntimeExtensionRequest,
47    RuntimeTier,
48};
49pub use secret_ref::SecretRef;
50pub use secret_resolver::{SecretResolutionError, SecretResolver};
51pub use secret_value::SecretValue;
52pub use task_state::TaskState;
53pub use tool_types::{
54    ToolCoreOutcome, ToolCoreRequest, ToolExtensionOutcome, ToolExtensionRequest, ToolTier,
55};
56pub use work_types::{
57    WorkRuntimeHealthSnapshot, WorkSourceKind, WorkUnitEventRecord, WorkUnitKind,
58    WorkUnitLeaseRecord, WorkUnitPriority, WorkUnitRecord, WorkUnitRetryPolicy, WorkUnitSnapshot,
59    WorkUnitSourceRef, WorkUnitStatus,
60};
61pub use workflow_types::{
62    GovernedSessionBindingDescriptor, GovernedSessionMode, GovernedWorkflowPhase,
63    TaskScopeDescriptor, WorkflowOperationKind, WorkflowOperationScope, WorktreeBindingDescriptor,
64};
65
66#[cfg(test)]
67mod secret_contract_tests {
68    use std::path::PathBuf;
69
70    use serde::{Deserialize, Serialize};
71
72    use super::{SecretRef, SecretValue};
73
74    #[derive(Debug, Deserialize, Serialize)]
75    struct SecretHolder {
76        secret: SecretRef,
77    }
78
79    #[test]
80    fn secret_ref_toml_string_parses_as_inline_literal() {
81        let raw = r#"secret = "sk-inline-secret""#;
82
83        let parsed = toml::from_str::<SecretHolder>(raw).expect("inline secret should parse");
84
85        assert_eq!(
86            parsed.secret,
87            SecretRef::Inline("sk-inline-secret".to_owned())
88        );
89    }
90
91    #[test]
92    fn secret_ref_toml_dollar_reference_parses_as_env_variant() {
93        let raw = r#"secret = "${OPENAI_API_KEY}""#;
94
95        let parsed = toml::from_str::<SecretHolder>(raw).expect("env reference should parse");
96
97        assert_eq!(
98            parsed.secret,
99            SecretRef::Env {
100                env: "OPENAI_API_KEY".to_owned(),
101            }
102        );
103    }
104
105    #[test]
106    fn secret_ref_toml_file_table_parses_as_file_variant() {
107        let raw = r#"secret = { file = "/run/secrets/openai" }"#;
108
109        let parsed = toml::from_str::<SecretHolder>(raw).expect("file secret should parse");
110
111        assert_eq!(
112            parsed.secret,
113            SecretRef::File {
114                file: PathBuf::from("/run/secrets/openai"),
115            }
116        );
117    }
118
119    #[test]
120    fn secret_ref_toml_exec_table_parses_as_exec_variant() {
121        let raw = r#"secret = { exec = ["op", "read", "op://vault/openai/token"] }"#;
122
123        let parsed = toml::from_str::<SecretHolder>(raw).expect("exec secret should parse");
124
125        assert_eq!(
126            parsed.secret,
127            SecretRef::Exec {
128                exec: vec![
129                    "op".to_owned(),
130                    "read".to_owned(),
131                    "op://vault/openai/token".to_owned(),
132                ],
133            }
134        );
135    }
136
137    #[test]
138    fn secret_ref_rejects_table_with_multiple_variants() {
139        let raw = r#"secret = { env = "OPENAI_API_KEY", file = "/run/secrets/openai" }"#;
140
141        let error = toml::from_str::<SecretHolder>(raw)
142            .expect_err("multiple variant keys should be rejected");
143
144        let rendered = error.to_string();
145
146        assert!(rendered.contains("exactly one"));
147        assert!(rendered.contains("env"));
148        assert!(rendered.contains("file"));
149    }
150
151    #[test]
152    fn secret_ref_rejects_unknown_table_key() {
153        let raw = r#"secret = { provider = "vault" }"#;
154
155        let error =
156            toml::from_str::<SecretHolder>(raw).expect_err("unknown key should be rejected");
157
158        assert!(error.to_string().contains("unknown field"));
159    }
160
161    #[test]
162    fn secret_ref_debug_redacts_inline_value() {
163        let secret = SecretRef::Inline("sk-inline-secret".to_owned());
164
165        let rendered = format!("{secret:?}");
166
167        assert!(rendered.contains("<redacted>"));
168        assert!(!rendered.contains("sk-inline-secret"));
169    }
170
171    #[test]
172    fn secret_ref_toml_serialize_round_trips_inline_literal() {
173        let holder = SecretHolder {
174            secret: SecretRef::Inline("sk-inline-secret".to_owned()),
175        };
176
177        let encoded = toml::to_string(&holder).expect("inline secret should serialize");
178
179        assert!(encoded.contains("sk-inline-secret"));
180        assert!(!encoded.contains("<redacted>"));
181    }
182
183    #[test]
184    fn secret_ref_explicit_env_name_supports_inline_compatibility_formats() {
185        let cases = vec![
186            ("${LOONG_SECRET}", Some("LOONG_SECRET")),
187            ("$LOONG_SECRET", Some("LOONG_SECRET")),
188            ("env:LOONG_SECRET", Some("LOONG_SECRET")),
189            ("%LOONG_SECRET%", Some("LOONG_SECRET")),
190            ("sk-inline-secret", None),
191        ];
192
193        for (raw_value, expected_env_name) in cases {
194            let secret = SecretRef::Inline(raw_value.to_owned());
195            let env_name = secret.explicit_env_name();
196            assert_eq!(env_name.as_deref(), expected_env_name);
197        }
198    }
199
200    #[test]
201    fn secret_ref_inline_literal_value_excludes_compatibility_env_references() {
202        let literal_secret = SecretRef::Inline(" sk-inline-secret ".to_owned());
203        let env_reference = SecretRef::Inline("${LOONG_SECRET}".to_owned());
204
205        assert_eq!(
206            literal_secret.inline_literal_value(),
207            Some("sk-inline-secret")
208        );
209        assert_eq!(env_reference.inline_literal_value(), None);
210        assert!(literal_secret.is_configured());
211        assert!(env_reference.is_configured());
212        assert!(!SecretRef::Inline("   ".to_owned()).is_configured());
213    }
214
215    #[test]
216    fn secret_value_exposes_inner_string() {
217        let secret = SecretValue::new("value".to_owned());
218
219        assert_eq!(secret.expose(), "value");
220    }
221}