ma_core/config/cli.rs
1//! Command-line argument struct for ma-core-based binaries.
2//!
3//! Flatten [`MaArgs`] into your own `#[derive(Parser)]` struct so that every
4//! binary in the ma ecosystem accepts a consistent set of arguments:
5//!
6//! ```rust,ignore
7//! use clap::Parser;
8//! use ma_core::config::MaArgs;
9//!
10//! const MA_DEFAULT_SLUG: &str = "panteia";
11//!
12//! #[derive(Parser)]
13//! struct Cli {
14//! #[command(flatten)]
15//! ma: MaArgs,
16//! }
17//!
18//! fn main() -> anyhow::Result<()> {
19//! let cli = Cli::parse();
20//! let config = ma_core::config::Config::from_args(&cli.ma, MA_DEFAULT_SLUG)?;
21//! config.init_logging()?;
22//! Ok(())
23//! }
24//! ```
25
26use std::path::PathBuf;
27
28use clap::Args;
29
30/// Standard ma-core CLI arguments.
31///
32/// Add these to your binary with `#[command(flatten)]`.
33///
34/// All fields are resolved from `MA_*` environment variables, a YAML config
35/// file, and built-in defaults — in that priority order.
36#[derive(Args, Debug, Clone, Default)]
37pub struct MaArgs {
38 /// Path to the YAML config file. Overrides the slug-derived default
39 /// (`XDG_CONFIG_HOME/ma/<slug>.yaml`).
40 ///
41 /// Environment variable: `MA_CONFIG`
42 #[arg(long, env = "MA_CONFIG")]
43 pub config: Option<PathBuf>,
44
45 /// Runtime slug. Overrides `MA_DEFAULT_SLUG` for file naming
46 /// (`<slug>.yaml`, `<slug>.bin`, `<slug>.log`) only.
47 ///
48 /// Environment variable: `MA_SLUG`
49 #[arg(long, env = "MA_SLUG")]
50 pub slug: Option<String>,
51
52 /// Log level for the log file (`trace`, `debug`, `info`, `warn`, `error`).
53 ///
54 /// Environment variable: `MA_LOG_LEVEL`. Falls back to YAML → default `"info"`.
55 #[arg(long)]
56 pub log_level: Option<String>,
57
58 /// Path to the log file. Defaults to `XDG_DATA_HOME/ma/<slug>.log`.
59 ///
60 /// Environment variable: `MA_LOG_FILE`. Falls back to YAML → XDG default.
61 #[arg(long)]
62 pub log_file: Option<PathBuf>,
63
64 /// Log level for stdout output (`trace`, `debug`, `info`, `warn`, `error`).
65 ///
66 /// Environment variable: `MA_LOG_LEVEL_STDOUT`. Falls back to YAML → default `"warn"`.
67 #[arg(long)]
68 pub log_level_stdout: Option<String>,
69
70 /// Positive DID cache TTL in seconds.
71 ///
72 /// Set to `0` to disable caching successful DID resolutions.
73 /// Environment variable: `MA_DID_RESOLVER_POSITIVE_TTL_SECS`. Falls back to YAML → default `60`.
74 #[arg(long)]
75 pub did_resolver_positive_ttl_secs: Option<u64>,
76
77 /// Negative DID cache TTL in seconds.
78 ///
79 /// Set to `0` to disable caching failed DID resolutions.
80 /// Environment variable: `MA_DID_RESOLVER_NEGATIVE_TTL_SECS`. Falls back to YAML → default `10`.
81 #[arg(long)]
82 pub did_resolver_negative_ttl_secs: Option<u64>,
83
84 /// Path to the encrypted secret bundle file.
85 /// Defaults to `XDG_CONFIG_HOME/ma/<slug>.bin`.
86 ///
87 /// Environment variable: `MA_SECRET_BUNDLE`. Falls back to YAML → XDG default.
88 #[arg(long)]
89 pub secret_bundle: Option<PathBuf>,
90
91 /// Passphrase to unlock the secret bundle.
92 ///
93 /// In headless configs this is stored in cleartext in the YAML file.
94 /// Prefer setting via environment variable rather than CLI to avoid
95 /// shell history exposure.
96 ///
97 /// Environment variable: `MA_SECRET_BUNDLE_PASSPHRASE`. Falls back to YAML.
98 #[arg(long)]
99 pub secret_bundle_passphrase: Option<String>,
100
101 /// Kubo RPC API URL. Defaults to `http://127.0.0.1:5001`.
102 ///
103 /// Environment variable: `MA_KUBO_RPC_URL`. Falls back to YAML → default.
104 #[arg(long)]
105 pub kubo_rpc_url: Option<String>,
106
107 /// IPNS key alias used in Kubo. Defaults to the slug.
108 ///
109 /// Environment variable: `MA_KUBO_KEY_ALIAS`. Falls back to YAML → slug.
110 #[arg(long)]
111 pub kubo_key_alias: Option<String>,
112
113 /// Generate a headless config with a fresh secret bundle, write both
114 /// files with 0600 permissions, and exit.
115 ///
116 /// If `--secret-bundle-passphrase` is not provided, a random passphrase
117 /// is generated and written into the config file.
118 #[arg(long)]
119 pub gen_headless_config: bool,
120}