heddle_cli_args/cli/cli_args/commands_redact.rs
1// SPDX-License-Identifier: Apache-2.0
2//! `heddle redact` and `heddle redact purge` — the redaction primitive.
3//!
4//! See `docs/PRINCIPLES.md` and the build brief at
5//! `.agents/redaction-primitive.md` for the design rationale. Briefly:
6//!
7//! - `redact` declares a blob redacted; readers see a stub on
8//! materialize, but the bytes remain on disk.
9//! - `purge` removes the bytes from local storage. The `Redaction`
10//! tombstone stays in the DAG forever.
11//!
12//! Both verbs write `OpRecord` entries (`Redact`, `Purge`) so the
13//! oplog audit trail records who did what when.
14
15use clap::{Args, Subcommand};
16
17#[derive(Clone, Debug, Subcommand)]
18pub enum RedactCommands {
19 /// Declare a redaction on a blob in a state. The blob bytes stay
20 /// on disk; reads return the stub. Use `heddle redact purge` afterward
21 /// to physically remove the bytes.
22 Apply(RedactApplyArgs),
23 /// List every active redaction in the repo.
24 List(RedactListArgs),
25 /// Show a single redaction by its content-addressed id.
26 Show(RedactShowArgs),
27 /// Physically remove bytes for an existing redaction.
28 #[command(subcommand)]
29 Purge(PurgeCommands),
30}
31
32#[derive(Clone, Debug, Args)]
33pub struct RedactApplyArgs {
34 /// State that surfaces the file. Accepts short or full state IDs,
35 /// marker names, `HEAD`, `@`, or `HEAD~N`.
36 pub state: String,
37 /// Path within the state's tree.
38 #[arg(long)]
39 pub path: String,
40 /// Operator-supplied reason. Lands in the materialized stub so
41 /// reviewers know why content disappeared.
42 #[arg(long)]
43 pub reason: String,
44 /// Walk every reachable state and redact every occurrence of the
45 /// same blob hash. Default: just the named state.
46 #[arg(long)]
47 pub all_states: bool,
48 /// Path to a private key (PEM) used to sign the redaction. The
49 /// signature binds operator → declaration; auditors can verify
50 /// who hid what when with `heddle redact show`.
51 #[arg(long, value_name = "PATH")]
52 pub sign_with: Option<std::path::PathBuf>,
53 /// Override the signing algorithm. Defaults to autodetect from the
54 /// key file's PEM header. Accepts `ed25519`, `p256`.
55 #[arg(long, value_name = "ALGO", requires = "sign_with")]
56 pub sign_algo: Option<String>,
57}
58
59#[derive(Clone, Debug, Args)]
60pub struct RedactListArgs {}
61
62#[derive(Clone, Debug, Args)]
63pub struct RedactShowArgs {
64 /// Redaction id (full or short prefix).
65 pub redaction_id: String,
66}
67
68#[derive(Clone, Debug, Subcommand)]
69pub enum PurgeCommands {
70 /// Physically remove the blob bytes referenced by an existing
71 /// redaction. Refuses if no redaction declared the blob first.
72 ///
73 Apply(PurgeApplyArgs),
74 /// List every `Purge` oplog entry — who removed bytes, when, and
75 /// which redaction the purge acted on.
76 List(PurgeListArgs),
77}
78
79#[derive(Clone, Debug, Args)]
80pub struct PurgeApplyArgs {
81 /// State whose redaction we're purging the blob of.
82 pub state: String,
83 /// Path within the state's tree.
84 #[arg(long)]
85 pub path: String,
86 /// Required acknowledgement. Purge is irreversible — without
87 /// `--force` the command refuses, listing what would be removed.
88 #[arg(long)]
89 pub force: bool,
90}
91
92#[derive(Clone, Debug, Args)]
93pub struct PurgeListArgs {}