Skip to main content

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}