evorule_cli/cli.rs
1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (C) 2026 EvoRule Project
3// This file is part of EvoRule, licensed under GNU Affero General Public License v3 or later.
4//! CLI 参数定义(clap derive)
5//!
6//! 子命令:
7//! - `run`:加载并执行 JSON 规则,输出 fact log
8//! - `replay`:重放 fact log(pretty-print)
9//! - `diff`:对比两个 fact log(按 FactId 对齐)
10//! - `validate`:校验 JSON 规则文件(用 tier1 RuleValidator)
11//! - `verify-chain`:验证 fact log 哈希链完整性
12//! - `compile-evopack`:JSON 规则 → 紧凑 .evopack 二进制包(host 编译器)
13//! - `anchor-keygen`:生成 G-A1 审计锚点签名密钥对(一次性运维)
14//! - `verify-anchors`:离线校验 G-A1 审计锚点真实性(防抵赖)
15
16use std::path::PathBuf;
17
18use clap::{Parser, Subcommand};
19
20/// evorule: 没有智能,只有执行的最佳实践
21#[derive(Parser, Debug)]
22#[command(
23 name = "evorule",
24 version,
25 about = "evorule: no intelligence, only best practices of execution",
26 long_about = "evorule CLI - load and execute user-written JSON rules.\n\
27 Zero network, zero telemetry, zero system dependencies, suited for compliance-sensitive local use.\n\
28 The fact log uses the evorule-reactor WAL format, interoperable with the evorule-governance audit chain."
29)]
30pub struct Cli {
31 #[command(subcommand)]
32 pub command: Command,
33}
34
35#[derive(Subcommand, Debug)]
36pub enum Command {
37 /// Load and execute JSON rules (output a fact log)
38 Run {
39 /// Rules directory (contains *.json files)
40 rules_dir: PathBuf,
41
42 /// Initial payload (JSON string, optional, default {})
43 #[arg(long, conflicts_with = "payload_file")]
44 payload: Option<String>,
45
46 /// Read initial payload from a file (JSON format)
47 #[arg(long)]
48 payload_file: Option<PathBuf>,
49
50 /// Output file (default stdout)
51 #[arg(long, short = 'o')]
52 output: Option<PathBuf>,
53
54 /// Maximum execution step limit (default 10000; emit Fact::Error and exit when exceeded)
55 #[arg(long, default_value_t = crate::executor::DEFAULT_MAX_STEPS)]
56 max_steps: usize,
57 },
58
59 /// Replay a fact log (pretty-print each Fact)
60 Replay {
61 /// Fact log file (JSON Lines format, interoperable with the tier1 reactor WAL)
62 fact_log: PathBuf,
63 },
64
65 /// Compare two fact logs (aligned by FactId, not HashSet)
66 Diff {
67 /// First fact log
68 a: PathBuf,
69 /// Second fact log
70 b: PathBuf,
71 },
72
73 /// Validate JSON rule files (tier1 RuleValidator, syntactic + semantic validation)
74 Validate {
75 /// Rules directory
76 rules_dir: PathBuf,
77 },
78
79 /// Verify fact log hash chain integrity (blake3, interoperable with evorule-governance)
80 VerifyChain {
81 /// Fact log file
82 fact_log: PathBuf,
83 },
84
85 /// Audit chain sentinel: scan a WAL directory, verify every chain end-to-end,
86 /// and compare against the previous scan baseline (prefix-anchored: pure
87 /// appends vs. history-rewritten recalculation are distinguished precisely).
88 /// Exit codes: 0 ok / 2 self-test failed / 3 chain broken / 4 file gone / 5 partial line.
89 ScanWalDir {
90 /// WAL directory (session_*.wal*, shared_facts.wal, governance_single_reactor.wal)
91 wal_dir: PathBuf,
92
93 /// Baseline file for cross-scan comparison (first run creates it)
94 #[arg(long)]
95 baseline: Option<PathBuf>,
96
97 /// Append-only sentinel log (one line per file per scan; keep in a separate dir)
98 #[arg(long)]
99 sentinel_log: Option<PathBuf>,
100
101 /// Machine-readable JSON report output file
102 #[arg(long)]
103 json: Option<PathBuf>,
104 },
105
106 /// Controlled recovery: truncate a WAL file to its last complete line, with
107 /// prefix chain verification report and .partial.bak backup (dry-run unless --confirm)
108 TruncatePartialLine {
109 /// WAL file (with a partial trailing line)
110 wal_file: PathBuf,
111
112 /// Confirm on-disk truncation (default: dry-run)
113 #[arg(long)]
114 confirm: bool,
115 },
116
117 /// Compile JSON rules into a compact .evopack binary package (host compiler for the embedded no_std kernel)
118 ///
119 /// Deterministic: the same input rules always produce the same bytes (postcard canonical
120 /// encoding, BTreeMap key order), the artifact can be burned into MCU firmware or used for
121 /// QEMU cross-validation against the no_std kernel. Rule count exceeding the TCB upper limit
122 /// (MAX_TRANSFORM_RULES) is rejected at compile time (fail-fast).
123 CompileEvopack {
124 /// Rules file (JSON: {"transform": [...]}, {"transforms": [...]}, top-level array, or single object)
125 rules_file: PathBuf,
126
127 /// Output .evopack binary file
128 #[arg(short = 'o')]
129 output: PathBuf,
130 },
131
132 /// Generate a G-A1 audit anchor signing keypair (one-time ops)
133 ///
134 /// Produces a private seed (32 bytes, 64 hex chars) and a public key (32 bytes, 64 hex chars).
135 /// Keep the private key secret; it is used to configure the auditor signing anchor. The public key
136 /// can be distributed to third parties for offline verification with `verify-anchors`.
137 AnchorKeygen {
138 /// File to write the private seed to (default: print to stdout)
139 #[arg(long)]
140 output: Option<PathBuf>,
141 },
142
143 /// Derive the verification public key from a private seed (deployment companion)
144 ///
145 /// The deployment (evorule-server `EVORULE_ANCHOR_SEED`) holds only the seed;
146 /// verifiers need only the public key. Prints the derived public key for
147 /// secure distribution. Use `--seed -` to read the seed from stdin.
148 AnchorPubkey {
149 /// Private seed (64 hex chars), or `-` to read one line from stdin
150 seed: String,
151 },
152
153 /// Verify G-A1 audit anchors offline (anti-repudiation)
154 ///
155 /// Takes an audit export JSON produced by `evorule-governance` `Auditor::export()`.
156 /// Verifies each anchor's chain link and recomputes the payload signature with the public key,
157 /// proving the audit chain was actually produced by the private key holder.
158 VerifyAnchors {
159 /// Audit export JSON file
160 audit: PathBuf,
161 /// Public key hex (default: use the export's embedded verifying_key)
162 #[arg(long)]
163 pubkey: Option<String>,
164 },
165}