1use garde::Validate;
4use secrecy::SecretString;
5
6use agentics_domain::models::auth::GithubUserId;
7use agentics_domain::models::names::MoltbookSubmoltName;
8use agentics_domain::models::urls::{
9 GithubApiUserUrl, GithubAppAuthorizeUrl, GithubAppRedirectUrl, GithubAppTokenUrl,
10 MoltbookSubmoltUrl,
11};
12
13use crate::runtime_modes::{
14 AgentRegistrationMode, HostProbeMode, OfficialLogRedactionMode, RunnerNamespace,
15 RunnerSecurityProfile, RunnerWritableStorageMode, WorkerAccelerators,
16};
17use crate::storage_config::StorageBackend;
18use crate::validation;
19
20#[derive(Debug, Clone, Validate)]
22#[garde(allow_unvalidated)]
23pub struct Config {
24 #[garde(dive)]
25 pub database: DatabaseConfig,
26 #[garde(dive)]
27 pub api_web: ApiWebConfig,
28 #[garde(dive)]
29 pub storage: StorageConfig,
30 #[garde(dive)]
31 pub auth: AuthConfig,
32 #[garde(dive)]
33 pub moltbook: MoltbookConfig,
34 #[garde(dive)]
35 pub worker: WorkerConfig,
36 #[garde(dive)]
37 pub quotas: QuotaConfig,
38 #[garde(dive)]
39 pub github_app: GithubAppConfig,
40 #[garde(dive)]
41 pub runner: RunnerConfig,
42 #[garde(dive)]
43 pub logging: LoggingConfig,
44}
45
46#[derive(Debug, Clone, Validate)]
48#[garde(allow_unvalidated)]
49pub struct DatabaseConfig {
50 pub url: SecretString,
51}
52
53#[derive(Debug, Clone, Validate)]
55#[garde(allow_unvalidated)]
56pub struct ApiWebConfig {
57 pub api_host: String,
58 pub api_port: u16,
59 #[garde(custom(validation::cors_origin_list))]
60 pub cors_allowed_origins: String,
61 #[garde(custom(validation::cookie_name))]
62 pub web_session_cookie_name: String,
63 #[garde(custom(validation::cookie_name))]
64 pub web_csrf_cookie_name: String,
65 #[garde(range(min = 1))]
66 pub web_session_ttl_hours: i64,
67 pub web_session_cookie_secure: bool,
68}
69
70#[derive(Debug, Clone, Validate)]
72#[garde(allow_unvalidated)]
73pub struct StorageConfig {
74 pub root: String,
75 pub backend: StorageBackend,
76 #[garde(custom(validation::optional_absolute_path))]
77 pub work_root: Option<String>,
78 pub s3_bucket: Option<String>,
79 pub s3_prefix: Option<String>,
80 pub s3_region: String,
81 pub s3_endpoint_url: Option<url::Url>,
82 pub s3_force_path_style: bool,
83 #[garde(range(min = 1))]
84 pub max_bundle_archive_bytes: u64,
85 #[garde(range(min = 1))]
86 pub max_statement_bytes: u64,
87 #[garde(range(min = 1))]
88 pub max_json_artifact_bytes: u64,
89 #[garde(range(min = 1))]
90 pub tmp_object_grace_hours: u64,
91 pub challenges_root: String,
92}
93
94#[derive(Debug, Clone, Validate)]
96#[garde(allow_unvalidated)]
97pub struct AuthConfig {
98 pub bootstrap_admin_github_user_ids: Vec<GithubUserId>,
99 pub agent_registration_mode: AgentRegistrationMode,
100}
101
102#[derive(Debug, Clone, Validate)]
104#[garde(allow_unvalidated)]
105pub struct MoltbookConfig {
106 pub submolt_name: MoltbookSubmoltName,
107 pub submolt_url: MoltbookSubmoltUrl,
108}
109
110#[derive(Debug, Clone, Validate)]
112#[garde(allow_unvalidated)]
113pub struct WorkerConfig {
114 #[garde(range(min = 1))]
115 pub poll_interval_ms: u64,
116 #[garde(range(min = 1))]
117 pub stale_job_minutes: i32,
118 pub accelerators: WorkerAccelerators,
119 #[garde(custom(validation::optional_trimmed_non_empty))]
120 pub gpu_probe_image: Option<String>,
121}
122
123#[derive(Debug, Clone, Validate)]
125#[garde(allow_unvalidated)]
126pub struct QuotaConfig {
127 #[garde(range(min = 1))]
128 pub validation_runs_per_agent_challenge_day: u32,
129 #[garde(range(min = 1))]
130 pub official_runs_per_agent_challenge_day: u32,
131 #[garde(range(min = 1))]
132 pub max_active_official_jobs: u32,
133 #[garde(range(min = 1))]
134 pub max_active_agents: u32,
135 #[garde(range(min = 1))]
136 pub max_active_challenge_review_records_per_human: u32,
137 #[garde(range(min = 1))]
138 pub challenge_private_asset_bytes_per_review_record: u64,
139 #[garde(range(min = 1))]
140 pub challenge_review_record_validations_per_day: u32,
141 #[garde(range(min = 1))]
142 pub challenge_review_record_validation_timeout_minutes: i32,
143 #[garde(range(min = 1))]
144 pub challenge_private_asset_pending_timeout_minutes: i32,
145 #[garde(range(min = 1))]
146 pub challenge_review_record_publish_timeout_minutes: i32,
147 #[garde(range(min = 1))]
148 pub challenge_review_record_ttl_days: i64,
149 #[garde(range(min = 1))]
150 pub unpublished_challenge_asset_grace_days: i64,
151}
152
153#[derive(Debug, Clone, Validate)]
155#[garde(allow_unvalidated)]
156pub struct GithubAppConfig {
157 #[garde(custom(validation::optional_trimmed_non_empty))]
158 pub client_id: Option<String>,
159 #[garde(custom(validation::optional_secret_non_empty))]
160 pub client_secret: Option<SecretString>,
161 pub redirect_url: Option<GithubAppRedirectUrl>,
162 pub authorize_url: GithubAppAuthorizeUrl,
163 pub token_url: GithubAppTokenUrl,
164 pub api_user_url: GithubApiUserUrl,
165}
166
167#[derive(Debug, Clone, Validate)]
169#[garde(allow_unvalidated)]
170pub struct RunnerConfig {
171 pub docker_host: Option<String>,
173 pub host_probe_mode: HostProbeMode,
174 #[garde(custom(validation::trimmed_non_empty))]
175 pub host_probe_command: String,
176 pub security_profile: RunnerSecurityProfile,
177 pub official_log_redaction: OfficialLogRedactionMode,
178 pub require_digest_pinned_images: bool,
179 pub writable_storage_mode: RunnerWritableStorageMode,
180 pub namespace: RunnerNamespace,
181 #[garde(custom(validation::optional_absolute_path))]
182 pub runtime_root: Option<String>,
183 #[garde(custom(validation::optional_absolute_path))]
184 pub phase_mount_root: Option<String>,
185 #[garde(custom(validation::runner_slot_class_csv))]
186 pub writable_slot_classes_mb: String,
187 pub docker_layer_quota: bool,
188 #[garde(range(min = 1))]
189 pub max_output_files: u64,
190 #[garde(range(min = 1))]
191 pub max_output_dirs: u64,
192 #[garde(range(min = 1))]
193 pub max_output_depth: u64,
194 #[garde(range(min = 1, max = agentics_contracts::challenge_bundle::MAX_CHALLENGE_RUNS_PER_EVALUATION))]
195 pub max_runs: u64,
196 #[garde(range(min = 1))]
197 pub max_result_json_bytes: u64,
198 #[garde(range(min = 1))]
199 pub max_public_results: u64,
200 #[garde(range(min = 1))]
201 pub max_result_log_bytes: u64,
202 #[garde(range(min = 1))]
203 pub max_interaction_bytes_per_direction: u64,
204 #[garde(range(min = 1))]
205 pub interaction_shutdown_grace_secs: u64,
206}
207
208#[derive(Debug, Clone, Validate)]
210#[garde(allow_unvalidated)]
211pub struct LoggingConfig {
212 #[garde(custom(validation::trimmed_non_empty))]
213 pub log_level: String,
214}