pharos_native/runtime/runtime_reports.rs
1//! Bounded JSON report builders for runtime and app operations.
2
3use std::path::Path;
4
5use serde_json::{Map, Value};
6
7use crate::config::AppRuntime;
8
9use super::RuntimeStack;
10
11/// Performs app summary.
12fn app_summary(app: &AppRuntime) -> Value {
13 let backend = app
14 .app_root
15 .as_deref()
16 .filter(|value| !value.is_empty())
17 .and_then(|app_root| {
18 super::database::dynamic_relational_backend(
19 Path::new(app_root),
20 app.runtime_conf_path.as_deref().map(Path::new),
21 )
22 })
23 .unwrap_or_else(|| "sqlite".to_owned());
24 let db_ready = super::database::runtime_database_ready(app).unwrap_or(false);
25 serde_json::json!({
26 "app_id": app.app_id.as_deref().unwrap_or_default(),
27 "mount_path": app.base_path.as_deref().unwrap_or_default(),
28 "app_root": app.app_root.as_deref().unwrap_or_default(),
29 "build_dir": app.build_dir.as_deref().unwrap_or_default(),
30 "state_path": app.state_path.as_deref().unwrap_or_default(),
31 "log_path": app.log_path.as_deref().unwrap_or_default(),
32 "log_format": app.log_format.as_deref().unwrap_or("service"),
33 "error_report_path": app.error_report_path.as_deref().unwrap_or_default(),
34 "log_level": app.log_level.as_deref().unwrap_or("WARN"),
35 "host_profile": app.host_profile.as_deref().unwrap_or_default(),
36 "runtime_conf_path": app.runtime_conf_path.as_deref().unwrap_or_default(),
37 "backend": {
38 "db_backend": backend,
39 "db_ready": db_ready,
40 },
41 })
42}
43
44/// Builds the native runtime build report.
45///
46/// # Parameters
47///
48/// - `target_id`: Input consumed by [`crate::runtime::runtime_reports::build_runtime_build_report_json`].
49/// - `conf_path`: Input consumed by [`crate::runtime::runtime_reports::build_runtime_build_report_json`].
50/// - `apps_dir`: Input consumed by [`crate::runtime::runtime_reports::build_runtime_build_report_json`].
51/// - `app_count`: Input consumed by [`crate::runtime::runtime_reports::build_runtime_build_report_json`].
52///
53/// # Returns
54///
55/// Returns the successful value produced by [`crate::runtime::runtime_reports::build_runtime_build_report_json`] or an error when the operation fails.
56///
57/// # Errors
58///
59/// Returns an error value when [`crate::runtime::runtime_reports::build_runtime_build_report_json`] cannot complete successfully.
60///
61/// # Examples
62///
63/// ```rust,ignore
64/// let _result = pharos_native::runtime::runtime_reports::build_runtime_build_report_json("dev_docs", std::path::Path::new("app.conf"), todo!(), todo!());
65/// ```
66///
67/// # Related
68///
69/// - [`crate::runtime::runtime_reports`] for adjacent helpers that share the same runtime surface.
70pub fn build_runtime_build_report_json(
71 target_id: &str,
72 conf_path: Option<&str>,
73 apps_dir: &str,
74 app_count: usize,
75) -> Result<String, &'static str> {
76 serde_json::to_string(&serde_json::json!({
77 "report_id": "pharos-runtime-build-v1",
78 "target_kind": "runtime",
79 "target_id": target_id,
80 "status": "built",
81 "app_count": app_count,
82 "config_path": conf_path.unwrap_or_default(),
83 "apps_dir": apps_dir,
84 }))
85 .map_err(|_| "runtime report encoding failed")
86}
87
88/// Builds the native app runtime report.
89///
90/// # Parameters
91///
92/// - `report_id`: Input consumed by [`crate::runtime::runtime_reports::build_app_runtime_report_json`].
93/// - `verb`: Input consumed by [`crate::runtime::runtime_reports::build_app_runtime_report_json`].
94/// - `host_target`: Input consumed by [`crate::runtime::runtime_reports::build_app_runtime_report_json`].
95/// - `host_mode`: Input consumed by [`crate::runtime::runtime_reports::build_app_runtime_report_json`].
96/// - `artifact_dir`: Input consumed by [`crate::runtime::runtime_reports::build_app_runtime_report_json`].
97/// - `app`: Input consumed by [`crate::runtime::runtime_reports::build_app_runtime_report_json`].
98///
99/// # Returns
100///
101/// Returns the successful value produced by [`crate::runtime::runtime_reports::build_app_runtime_report_json`] or an error when the operation fails.
102///
103/// # Errors
104///
105/// Returns an error value when [`crate::runtime::runtime_reports::build_app_runtime_report_json`] cannot complete successfully.
106///
107/// # Examples
108///
109/// ```rust,ignore
110/// let _result = pharos_native::runtime::runtime_reports::build_app_runtime_report_json(todo!(), todo!(), todo!(), todo!(), std::path::Path::new("build/dev_docs"), todo!());
111/// ```
112///
113/// # Related
114///
115/// - [`crate::runtime::runtime_reports`] for adjacent helpers that share the same runtime surface.
116pub fn build_app_runtime_report_json(
117 report_id: Option<&str>,
118 verb: Option<&str>,
119 host_target: Option<&str>,
120 host_mode: Option<&str>,
121 artifact_dir: Option<&str>,
122 app: &AppRuntime,
123) -> Result<String, &'static str> {
124 let mut report = Map::new();
125 report.insert(
126 "report_id".to_owned(),
127 Value::String(
128 report_id
129 .unwrap_or("pharos-local-app-runtime-v1")
130 .to_owned(),
131 ),
132 );
133 report.insert(
134 "verb".to_owned(),
135 Value::String(verb.unwrap_or("status").to_owned()),
136 );
137 report.insert("target_kind".to_owned(), Value::String("app".to_owned()));
138 report.insert(
139 "target_id".to_owned(),
140 Value::String(app.app_id.as_deref().unwrap_or_default().to_owned()),
141 );
142 report.insert("status".to_owned(), Value::String("ok".to_owned()));
143 report.insert(
144 "artifact_dir".to_owned(),
145 Value::String(artifact_dir.unwrap_or_default().to_owned()),
146 );
147 report.insert(
148 "runtime_launcher".to_owned(),
149 Value::Bool(matches!(verb, Some("run" | "probe" | "smoke"))),
150 );
151 report.insert(
152 "host_target".to_owned(),
153 Value::String(host_target.unwrap_or("native-host").to_owned()),
154 );
155 report.insert(
156 "host_mode".to_owned(),
157 Value::String(host_mode.unwrap_or("native-host-target").to_owned()),
158 );
159 report.insert(
160 "generated_by".to_owned(),
161 Value::String("pharos-native-runtime".to_owned()),
162 );
163 report.insert("runtime_summary".to_owned(), app_summary(app));
164 serde_json::to_string(&Value::Object(report)).map_err(|_| "app report encoding failed")
165}
166
167/// Builds the native runtime status report.
168///
169/// # Parameters
170///
171/// - `stack`: Input consumed by [`crate::runtime::runtime_reports::build_runtime_status_report_json`].
172/// - `apps_dir`: Input consumed by [`crate::runtime::runtime_reports::build_runtime_status_report_json`].
173///
174/// # Returns
175///
176/// Returns the successful value produced by [`crate::runtime::runtime_reports::build_runtime_status_report_json`] or an error when the operation fails.
177///
178/// # Errors
179///
180/// Returns an error value when [`crate::runtime::runtime_reports::build_runtime_status_report_json`] cannot complete successfully.
181///
182/// # Performance
183///
184/// Performance is proportional to the size of the supplied inputs and any parsed or loaded data consumed by [`crate::runtime::runtime_reports::build_runtime_status_report_json`].
185///
186/// # Examples
187///
188/// ```rust,ignore
189/// let _result = pharos_native::runtime::runtime_reports::build_runtime_status_report_json(todo!(), todo!());
190/// ```
191///
192/// # Related
193///
194/// - [`crate::runtime::runtime_reports`] for adjacent helpers that share the same runtime surface.
195pub fn build_runtime_status_report_json(
196 stack: &RuntimeStack,
197 apps_dir: &str,
198) -> Result<String, &'static str> {
199 let apps: Vec<Value> = stack.apps.iter().map(app_summary).collect();
200 serde_json::to_string(&serde_json::json!({
201 "report_id": "pharos-runtime-status-v1",
202 "status": "ok",
203 "host": stack.host.as_deref().unwrap_or("127.0.0.1"),
204 "port": stack.port.as_deref().unwrap_or("7323"),
205 "socket_path": stack.socket_path.as_deref().unwrap_or_default(),
206 "redis_status": crate::runtime::cache::redis_status(),
207 "apps_dir": apps_dir,
208 "app_count": apps.len(),
209 "apps": apps,
210 }))
211 .map_err(|_| "status report encoding failed")
212}
213
214/// Builds a migration operation report with an explicit result status.
215///
216/// # Parameters
217///
218/// - `target_id`: Input consumed by [`crate::runtime::runtime_reports::build_migrate_operation_report_json`].
219/// - `backend`: Input consumed by [`crate::runtime::runtime_reports::build_migrate_operation_report_json`].
220/// - `operation`: Input consumed by [`crate::runtime::runtime_reports::build_migrate_operation_report_json`].
221/// - `status`: Input consumed by [`crate::runtime::runtime_reports::build_migrate_operation_report_json`].
222/// - `error`: Input consumed by [`crate::runtime::runtime_reports::build_migrate_operation_report_json`].
223///
224/// # Returns
225///
226/// Returns the successful value produced by [`crate::runtime::runtime_reports::build_migrate_operation_report_json`] or an error when the operation fails.
227///
228/// # Errors
229///
230/// Returns an error value when [`crate::runtime::runtime_reports::build_migrate_operation_report_json`] cannot complete successfully.
231///
232/// # Examples
233///
234/// ```rust,ignore
235/// let _result = pharos_native::runtime::runtime_reports::build_migrate_operation_report_json("dev_docs", todo!(), todo!(), 400, todo!());
236/// ```
237///
238/// # Related
239///
240/// - [`crate::runtime::runtime_reports`] for adjacent helpers that share the same runtime surface.
241pub fn build_migrate_operation_report_json(
242 target_id: &str,
243 backend: &str,
244 operation: &str,
245 status: &str,
246 error: Option<&str>,
247) -> Result<String, &'static str> {
248 serde_json::to_string(&serde_json::json!({
249 "report_id": "pharos-migrate-v1",
250 "target_kind": "app",
251 "target_id": target_id,
252 "backend": backend,
253 "operation": operation,
254 "status": status,
255 "error": error,
256 }))
257 .map_err(|_| "migration report encoding failed")
258}
259
260/// Builds a bounded website status report from a discovered artifact root.
261///
262/// # Parameters
263///
264/// - `website`: Input consumed by [`crate::runtime::runtime_reports::build_website_status_report_json`].
265/// - `artifact_root`: Input consumed by [`crate::runtime::runtime_reports::build_website_status_report_json`].
266/// - `status`: Input consumed by [`crate::runtime::runtime_reports::build_website_status_report_json`].
267///
268/// # Returns
269///
270/// Returns the successful value produced by [`crate::runtime::runtime_reports::build_website_status_report_json`] or an error when the operation fails.
271///
272/// # Errors
273///
274/// Returns an error value when [`crate::runtime::runtime_reports::build_website_status_report_json`] cannot complete successfully.
275///
276/// # Examples
277///
278/// ```rust,ignore
279/// let _result = pharos_native::runtime::runtime_reports::build_website_status_report_json(todo!(), todo!(), 400);
280/// ```
281///
282/// # Related
283///
284/// - [`crate::runtime::runtime_reports`] for adjacent helpers that share the same runtime surface.
285pub fn build_website_status_report_json(
286 website: &str,
287 artifact_root: &std::path::Path,
288 status: &str,
289) -> Result<String, &'static str> {
290 if website.is_empty() || artifact_root.as_os_str().is_empty() || status.is_empty() {
291 return Err("website status inputs are incomplete");
292 }
293 serde_json::to_string(&serde_json::json!({
294 "report_id": "pharos-website-status-v1",
295 "website": website,
296 "artifact_root": artifact_root,
297 "status": status,
298 }))
299 .map_err(|_| "website status report encoding failed")
300}
301
302/// Resolves one website artifact directory below a trusted root.
303///
304/// # Parameters
305///
306/// - `root`: Input consumed by [`crate::runtime::runtime_reports::website_artifact_dir`].
307/// - `website`: Input consumed by [`crate::runtime::runtime_reports::website_artifact_dir`].
308///
309/// # Returns
310///
311/// Returns [`Some`] when [`crate::runtime::runtime_reports::website_artifact_dir`] can produce a value and [`None`] otherwise.
312///
313/// # Examples
314///
315/// ```rust,ignore
316/// let _result = pharos_native::runtime::runtime_reports::website_artifact_dir(std::path::Path::new("."), todo!());
317/// ```
318///
319/// # Related
320///
321/// - [`crate::runtime::runtime_reports`] for adjacent helpers that share the same runtime surface.
322pub fn website_artifact_dir(root: &std::path::Path, website: &str) -> Option<String> {
323 if root.as_os_str().is_empty() || website.is_empty() || website.contains(['/', '\\']) {
324 return None;
325 }
326 let path = root.join("apps").join(website);
327 path.is_dir().then(|| path.to_string_lossy().into_owned())
328}
329
330/// Builds a compact runtime summary from one loaded app.
331///
332/// # Parameters
333///
334/// - `app`: Input consumed by [`crate::runtime::runtime_reports::build_runtime_summary_json_from_app`].
335///
336/// # Returns
337///
338/// Returns the successful value produced by [`crate::runtime::runtime_reports::build_runtime_summary_json_from_app`] or an error when the operation fails.
339///
340/// # Errors
341///
342/// Returns an error value when [`crate::runtime::runtime_reports::build_runtime_summary_json_from_app`] cannot complete successfully.
343///
344/// # Examples
345///
346/// ```rust,ignore
347/// let _result = pharos_native::runtime::runtime_reports::build_runtime_summary_json_from_app(todo!());
348/// ```
349///
350/// # Related
351///
352/// - [`crate::runtime::runtime_reports`] for adjacent helpers that share the same runtime surface.
353pub fn build_runtime_summary_json_from_app(app: &AppRuntime) -> Result<String, &'static str> {
354 serde_json::to_string(&app_summary(app)).map_err(|_| "runtime summary encoding failed")
355}
356
357/// Captures a bounded migration verification report without shell execution.
358///
359/// # Parameters
360///
361/// - `target_id`: Input consumed by [`crate::runtime::runtime_reports::capture_migrate_verify_report_json`].
362/// - `backend`: Input consumed by [`crate::runtime::runtime_reports::capture_migrate_verify_report_json`].
363/// - `status`: Input consumed by [`crate::runtime::runtime_reports::capture_migrate_verify_report_json`].
364/// - `error`: Input consumed by [`crate::runtime::runtime_reports::capture_migrate_verify_report_json`].
365///
366/// # Returns
367///
368/// Returns the successful value produced by [`crate::runtime::runtime_reports::capture_migrate_verify_report_json`] or an error when the operation fails.
369///
370/// # Errors
371///
372/// Returns an error value when [`crate::runtime::runtime_reports::capture_migrate_verify_report_json`] cannot complete successfully.
373///
374/// # Examples
375///
376/// ```rust,ignore
377/// let _result = pharos_native::runtime::runtime_reports::capture_migrate_verify_report_json("dev_docs", todo!(), 400, todo!());
378/// ```
379///
380/// # Related
381///
382/// - [`crate::runtime::runtime_reports`] for adjacent helpers that share the same runtime surface.
383pub fn capture_migrate_verify_report_json(
384 target_id: &str,
385 backend: &str,
386 status: &str,
387 error: Option<&str>,
388) -> Result<String, &'static str> {
389 build_migrate_operation_report_json(target_id, backend, "verify", status, error)
390}