Skip to main content

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}