forjar 1.4.2

Rust-native Infrastructure as Code — bare-metal first, BLAKE3 state, provenance tracing
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
//! CLI Args structs for misc-related commands (core).

use std::path::PathBuf;

/// CLI arguments for the `init` command.
#[derive(clap::Args, Debug)]
pub struct InitArgs {
    /// Directory to initialize (default: current)
    #[arg(default_value = ".")]
    pub path: PathBuf,
}

/// CLI arguments for the `drift` command.
#[derive(clap::Args, Debug)]
pub struct DriftArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Target specific machine
    #[arg(short, long)]
    pub machine: Option<String>,

    /// State directory
    #[arg(long, default_value = "state")]
    pub state_dir: PathBuf,

    /// Exit non-zero on any drift (for CI/cron)
    #[arg(long)]
    pub tripwire: bool,

    /// Run command on drift detection
    #[arg(long)]
    pub alert_cmd: Option<String>,

    /// Auto-remediate: re-apply drifted resources to restore desired state
    #[arg(long)]
    pub auto_remediate: bool,

    /// Show what would be checked without connecting to machines
    #[arg(long)]
    pub dry_run: bool,

    /// Output drift report as JSON
    #[arg(long)]
    pub json: bool,

    /// FJ-211: Load param overrides from external YAML file
    #[arg(long)]
    pub env_file: Option<PathBuf>,

    /// FJ-210: Use workspace (overrides state dir to state/<workspace>/)
    #[arg(short = 'w', long)]
    pub workspace: Option<String>,
}

/// CLI arguments for the `history` command.
#[derive(clap::Args, Debug)]
pub struct HistoryArgs {
    /// State directory
    #[arg(long, default_value = "state")]
    pub state_dir: PathBuf,

    /// Show history for specific machine
    #[arg(short, long)]
    pub machine: Option<String>,

    /// Show last N applies (default: 10)
    #[arg(short = 'n', long, default_value = "10")]
    pub limit: usize,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,

    /// FJ-284: Show only events from the last duration (e.g., 24h, 7d, 30m)
    #[arg(long)]
    pub since: Option<String>,

    /// FJ-357: Show change history for a specific resource
    #[arg(long)]
    pub resource: Option<String>,
}

/// CLI arguments for the `destroy` command.
#[derive(clap::Args, Debug)]
pub struct DestroyArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Target specific machine
    #[arg(short, long)]
    pub machine: Option<String>,

    /// Skip confirmation prompt
    #[arg(long)]
    pub yes: bool,

    /// State directory
    #[arg(long, default_value = "state")]
    pub state_dir: PathBuf,
}

/// CLI arguments for the `import` command.
#[derive(clap::Args, Debug)]
pub struct ImportArgs {
    /// Machine address (IP, hostname, or 'localhost')
    #[arg(short, long)]
    pub addr: String,

    /// SSH user
    #[arg(short, long, default_value = "root")]
    pub user: String,

    /// Machine name (used as key in machines section)
    #[arg(short, long)]
    pub name: Option<String>,

    /// Output file
    #[arg(short, long, default_value = "forjar.yaml")]
    pub output: PathBuf,

    /// What to scan
    #[arg(long, value_delimiter = ',', default_value = "packages,files,services")]
    pub scan: Vec<String>,

    /// Smart filter: only include manually installed packages (not base system)
    #[arg(long)]
    pub smart: bool,
}

/// CLI arguments for the `show` command.
#[derive(clap::Args, Debug)]
pub struct ShowArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Show specific resource only
    #[arg(short, long)]
    pub resource: Option<String>,

    /// Output as JSON instead of YAML
    #[arg(long)]
    pub json: bool,
}

/// CLI arguments for the `check` command.
#[derive(clap::Args, Debug)]
pub struct CheckArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Target specific machine
    #[arg(short, long)]
    pub machine: Option<String>,

    /// Target specific resource
    #[arg(short, long)]
    pub resource: Option<String>,

    /// Filter to resources with this tag
    #[arg(long)]
    pub tag: Option<String>,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,
}

/// CLI arguments for the `diff` command.
#[derive(clap::Args, Debug)]
pub struct DiffArgs {
    /// First state directory (older)
    pub from: PathBuf,

    /// Second state directory (newer)
    pub to: PathBuf,

    /// Filter to specific machine
    #[arg(short, long)]
    pub machine: Option<String>,

    /// FJ-291: Filter to specific resource
    #[arg(short, long)]
    pub resource: Option<String>,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,
}

/// FJ-1389: Unified stack diff — resource, machine, param comparison.
#[derive(clap::Args, Debug)]
pub struct StackDiffArgs {
    /// First config file
    pub file1: PathBuf,

    /// Second config file
    pub file2: PathBuf,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,
}

/// CLI arguments for the `fmt` command.
#[derive(clap::Args, Debug)]
pub struct FmtArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Check formatting without writing (exit non-zero if unformatted)
    #[arg(long)]
    pub check: bool,
}

/// CLI arguments for the `lint` command.
#[derive(clap::Args, Debug)]
pub struct LintArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,

    /// FJ-221: Enable built-in policy rules (no_root_owner, require_tags, etc.)
    #[arg(long)]
    pub strict: bool,

    /// FJ-332: Auto-fix common lint issues (normalize quotes, sort keys)
    #[arg(long)]
    pub fix: bool,

    /// FJ-374: Custom lint rules from YAML file
    #[arg(long)]
    pub rules: Option<PathBuf>,

    /// FJ-2400: Show bashrs version used for script purification
    #[arg(long)]
    pub bashrs_version: bool,
}

/// CLI arguments for the `rollback` command.
#[derive(clap::Args, Debug)]
pub struct RollbackArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Git revision to rollback to (default: HEAD~1)
    #[arg(short = 'n', long, default_value = "1")]
    pub revision: u32,

    /// FJ-1386: Rollback to a specific state generation (Nix-style)
    #[arg(long)]
    pub generation: Option<u32>,

    /// Target specific machine
    #[arg(short, long)]
    pub machine: Option<String>,

    /// Show what would change without applying
    #[arg(long)]
    pub dry_run: bool,

    /// Confirm destructive operation
    #[arg(long)]
    pub yes: bool,

    /// State directory
    #[arg(long, default_value = "state")]
    pub state_dir: PathBuf,
}

/// CLI arguments for the `anomaly` command.
#[derive(clap::Args, Debug)]
pub struct AnomalyArgs {
    /// State directory
    #[arg(long, default_value = "state")]
    pub state_dir: PathBuf,

    /// Target specific machine
    #[arg(short, long)]
    pub machine: Option<String>,

    /// Minimum events to consider (ignore resources with fewer)
    #[arg(long, default_value = "3")]
    pub min_events: usize,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,
}

/// CLI arguments for the `trace` command.
#[derive(clap::Args, Debug)]
pub struct TraceArgs {
    /// State directory
    #[arg(long, default_value = "state")]
    pub state_dir: PathBuf,

    /// Target specific machine
    #[arg(short, long)]
    pub machine: Option<String>,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,
}

/// CLI arguments for the `migrate` command.
#[derive(clap::Args, Debug)]
pub struct MigrateArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Write migrated config to file (default: stdout)
    #[arg(short, long)]
    pub output: Option<PathBuf>,
}

/// CLI arguments for the `mcp` command.
#[derive(clap::Args, Debug)]
pub struct McpArgs {
    /// Export tool schemas as JSON instead of starting server
    #[arg(long)]
    pub schema: bool,
}

/// CLI arguments for the `bench` command.
#[derive(clap::Args, Debug)]
pub struct BenchArgs {
    /// Number of iterations per benchmark (default: 1000)
    #[arg(long, default_value = "1000")]
    pub iterations: usize,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,

    /// Compare against stored baseline in benchmarks/RESULTS.md
    #[arg(long)]
    pub compare: bool,
}

/// CLI arguments for the `output` command.
#[derive(clap::Args, Debug)]
pub struct OutputArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Specific output key to show (omit for all)
    pub key: Option<String>,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,
}

/// CLI arguments for the `policy` command.
#[derive(clap::Args, Debug)]
pub struct PolicyArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,

    /// FJ-3207: Output as SARIF 2.1.0 (for GitHub Code Scanning / CI)
    #[arg(long)]
    pub sarif: bool,
}

/// FJ-3208: CLI arguments for the `policy-coverage` command.
#[derive(clap::Args, Debug)]
pub struct PolicyCoverageArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,
}

/// FJ-3206: CLI arguments for the `policy-install` command.
#[derive(clap::Args, Debug)]
pub struct PolicyInstallArgs {
    /// Pack name (e.g., cis-ubuntu-22, nist-800-53, soc2, hipaa)
    pub pack: String,
    /// Output directory for installed pack
    #[arg(long, default_value = "policies")]
    pub output_dir: PathBuf,
    /// Output as JSON
    #[arg(long)]
    pub json: bool,
}

/// CLI arguments for the `score` command.
#[derive(clap::Args, Debug)]
pub struct ScoreArgs {
    /// Path to forjar.yaml
    #[arg(short, long, default_value = "forjar.yaml")]
    pub file: PathBuf,

    /// Recipe status (qualified, blocked, pending)
    #[arg(long, default_value = "qualified")]
    pub status: String,

    /// Idempotency class (strong, weak, eventual)
    #[arg(long, default_value = "strong")]
    pub idempotency: String,

    /// Performance budget in milliseconds (0 = no budget)
    #[arg(long, default_value_t = 0)]
    pub budget_ms: u64,

    /// Output as JSON
    #[arg(long)]
    pub json: bool,

    /// FJ-3020: State directory for runtime data (events.jsonl)
    #[arg(long, default_value = "state")]
    pub state_dir: PathBuf,
}

/// FJ-1383: Merge two config files into one.
#[derive(clap::Args, Debug)]
pub struct ConfigMergeArgs {
    /// First config file
    pub file_a: std::path::PathBuf,

    /// Second config file
    pub file_b: std::path::PathBuf,

    /// Output file (default: stdout)
    #[arg(short, long)]
    pub output: Option<std::path::PathBuf>,

    /// Allow resource ID collisions (right takes precedence)
    #[arg(long)]
    pub allow_collisions: bool,
}

// SecurityScan, Sbom, Cbom, Prove, Extract, PrivilegeAnalysis, Provenance, Lineage
// args moved to misc_analysis_args.rs