atlas_cli/cli/
commands.rs

1use clap::Subcommand;
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, clap::ValueEnum)]
5pub enum HashAlgorithmChoice {
6    Sha256,
7    Sha384,
8    Sha512,
9}
10
11impl HashAlgorithmChoice {
12    pub fn to_cose_algorithm(&self) -> atlas_c2pa_lib::cose::HashAlgorithm {
13        match self {
14            HashAlgorithmChoice::Sha256 => atlas_c2pa_lib::cose::HashAlgorithm::Sha256,
15            HashAlgorithmChoice::Sha384 => atlas_c2pa_lib::cose::HashAlgorithm::Sha384,
16            HashAlgorithmChoice::Sha512 => atlas_c2pa_lib::cose::HashAlgorithm::Sha512,
17        }
18    }
19}
20
21#[derive(Debug, Subcommand)]
22pub enum DatasetCommands {
23    /// Create a new dataset manifest
24    Create {
25        #[arg(long = "paths", num_args = 1.., value_delimiter = ',')]
26        paths: Vec<PathBuf>,
27
28        /// Names for each ingredient (comma-separated)
29        #[arg(long = "ingredient-names", num_args = 1.., value_delimiter = ',')]
30        ingredient_names: Vec<String>,
31
32        /// Dataset name
33        #[arg(long = "name")]
34        name: String,
35
36        /// Author organization name
37        #[arg(long = "author-org")]
38        author_org: Option<String>,
39
40        /// Author name
41        #[arg(long = "author-name")]
42        author_name: Option<String>,
43
44        /// Optional description
45        #[arg(long = "description")]
46        description: Option<String>,
47
48        /// Optional linked manifest IDs
49        #[arg(long = "linked-manifests")]
50        linked_manifests: Option<Vec<String>>,
51
52        /// Path to private key file for signing (PEM format)
53        #[arg(long = "key")]
54        key: Option<PathBuf>,
55
56        /// Hash algorithm to use for signing (default: sha384)
57        #[arg(long = "hash-alg", value_enum, default_value = "sha384")]
58        hash_alg: HashAlgorithmChoice,
59
60        /// Only print manifest without storing
61        #[arg(long = "print")]
62        print: bool,
63
64        /// Output encoding (json or cbor)
65        #[arg(long = "encoding", default_value = "json")]
66        encoding: String,
67
68        /// Storage backend (local or rekor)
69        #[arg(long = "storage-type", default_value = "database")]
70        storage_type: Box<String>,
71
72        /// Storage URL
73        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
74        storage_url: Box<String>,
75
76        /// Collect the underlying TDX attestation, if available
77        #[arg(long = "with-tdx", default_value = "false")]
78        with_tdx: bool,
79    },
80    /// List all dataset manifests
81    List {
82        /// Storage backend (local or rekor)
83        #[arg(long = "storage-type", default_value = "database")]
84        storage_type: Box<String>,
85
86        /// Storage URL
87        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
88        storage_url: Box<String>,
89    },
90    Verify {
91        /// Manifest ID to verify
92        #[arg(long = "id")]
93        id: String,
94        /// Storage backend (local or rekor)
95        #[arg(long = "storage-type", default_value = "database")]
96        storage_type: Box<String>,
97
98        /// Storage URL
99        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
100        storage_url: Box<String>,
101    },
102}
103
104#[derive(Debug, Subcommand)]
105pub enum ModelCommands {
106    /// Create a new signed model manifest compliant with OpenSSF Model Signing (OMS) specification
107    Create {
108        /// Paths to the model ingredient files
109        #[arg(long = "paths", num_args = 1.., value_delimiter = ',')]
110        paths: Vec<PathBuf>,
111
112        /// Names for each ingredient (comma-separated)
113        #[arg(long = "ingredient-names", num_args = 1.., value_delimiter = ',')]
114        ingredient_names: Vec<String>,
115
116        /// Model name
117        #[arg(long = "name")]
118        name: String,
119
120        /// Author organization name
121        #[arg(long = "author-org")]
122        author_org: Option<String>,
123
124        /// Author name
125        #[arg(long = "author-name")]
126        author_name: Option<String>,
127
128        /// Optional description
129        #[arg(long = "description")]
130        description: Option<String>,
131
132        /// Optional linked manifest IDs
133        #[arg(long = "linked-manifests")]
134        linked_manifests: Option<Vec<String>>,
135
136        /// Path to private key file for signing (PEM format)
137        #[arg(long = "key")]
138        key: Option<PathBuf>,
139
140        /// Hash algorithm to use for signing (default: sha384)
141        #[arg(long = "hash-alg", value_enum, default_value = "sha384")]
142        hash_alg: HashAlgorithmChoice,
143
144        /// Only print manifest without storing
145        #[arg(long = "print")]
146        print: bool,
147
148        /// Encoding (json or cbor)
149        #[arg(long = "encoding", default_value = "json")]
150        encoding: String,
151
152        /// Format (standalone c2pa or oms)
153        #[arg(long = "format", default_value = "standalone")]
154        format: String,
155
156        /// Storage backend (local or rekor)
157        #[arg(long = "storage-type", default_value = "database")]
158        storage_type: Box<String>,
159
160        /// Storage URL
161        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
162        storage_url: Box<String>,
163
164        /// Collect the underlying CC attestation, if available
165        #[arg(long = "with-tdx", default_value = "false")]
166        with_tdx: bool,
167    },
168    /// List all model manifests
169    List {
170        /// Storage backend (local or rekor)
171        #[arg(long = "storage-type", default_value = "database")]
172        storage_type: Box<String>,
173
174        /// Storage URL
175        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
176        storage_url: Box<String>,
177    },
178    Verify {
179        /// Manifest ID to verify
180        #[arg(long = "id")]
181        id: String,
182        /// Storage backend (local or rekor)
183        #[arg(long = "storage-type", default_value = "database")]
184        storage_type: Box<String>,
185
186        /// Storage URL
187        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
188        storage_url: Box<String>,
189    },
190    LinkDataset {
191        /// Model manifest ID
192        #[arg(long = "model-id")]
193        model_id: String,
194
195        /// Dataset manifest ID
196        #[arg(long = "dataset-id")]
197        dataset_id: String,
198
199        /// Storage backend (local or rekor)
200        #[arg(long = "storage-type", default_value = "database")]
201        storage_type: Box<String>,
202
203        /// Storage URL
204        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
205        storage_url: Box<String>,
206    },
207}
208
209#[derive(Subcommand)]
210pub enum ManifestCommands {
211    /// Link manifests together
212    Link {
213        /// Source manifest ID
214        #[arg(short, long)]
215        source: String,
216
217        /// Target manifest ID
218        #[arg(short, long)]
219        target: String,
220
221        /// Storage backend (local or rekor)
222        #[arg(long = "storage-type", default_value = "database")]
223        storage_type: Box<String>,
224
225        /// Storage URL
226        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
227        storage_url: Box<String>,
228    },
229
230    /// Show manifest details
231    Show {
232        /// Manifest ID to show
233        #[arg(short, long)]
234        id: String,
235
236        /// Storage backend (local or rekor)
237        #[arg(long = "storage-type", default_value = "database")]
238        storage_type: Box<String>,
239
240        /// Storage URL
241        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
242        storage_url: Box<String>,
243    },
244
245    /// Validate manifest cross-references
246    Validate {
247        /// Manifest ID to validate
248        #[arg(short, long)]
249        id: String,
250
251        /// Storage backend (local or rekor)
252        #[arg(long = "storage-type", default_value = "database")]
253        storage_type: Box<String>,
254
255        /// Storage URL
256        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
257        storage_url: Box<String>,
258    },
259
260    /// Verify a specific link between two manifests
261    VerifyLink {
262        /// Source manifest ID
263        #[arg(short, long)]
264        source: String,
265
266        /// Target manifest ID
267        #[arg(short, long)]
268        target: String,
269
270        /// Storage backend (local or rekor)
271        #[arg(long = "storage-type", default_value = "database")]
272        storage_type: Box<String>,
273
274        /// Storage URL
275        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
276        storage_url: Box<String>,
277    },
278    /// Export provenance graph information
279    Export {
280        /// Manifest ID to export provenance for
281        #[arg(short, long)]
282        id: String,
283
284        /// Storage backend (local or rekor)
285        #[arg(long = "storage-type", default_value = "database")]
286        storage_type: Box<String>,
287
288        /// Storage URL
289        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
290        storage_url: Box<String>,
291
292        /// Output encoding (json or yaml)
293        #[arg(long = "encoding", default_value = "json")]
294        encoding: String,
295
296        /// Output file path (defaults to stdout if not provided)
297        #[arg(short, long)]
298        output: Option<String>,
299
300        /// Max depth to traverse the provenance graph (default: 10)
301        #[arg(long = "max-depth", default_value = "10")]
302        max_depth: u32,
303    },
304}
305/// Commands for evaluation results
306#[derive(Subcommand)]
307pub enum EvaluationCommands {
308    /// Create a new evaluation result manifest
309    Create {
310        /// Path to evaluation results file
311        #[arg(long = "path")]
312        path: PathBuf,
313
314        /// Evaluation name
315        #[arg(long = "name")]
316        name: String,
317
318        /// Model ID that was evaluated
319        #[arg(long = "model-id")]
320        model_id: String,
321
322        /// Evaluation dataset ID
323        #[arg(long = "dataset-id")]
324        dataset_id: String,
325
326        /// Evaluation metrics (key=value pairs)
327        #[arg(long = "metrics", num_args = 1.., value_delimiter = ',')]
328        metrics: Vec<String>,
329
330        /// Author organization name
331        #[arg(long = "author-org")]
332        author_org: Option<String>,
333
334        /// Author name
335        #[arg(long = "author-name")]
336        author_name: Option<String>,
337
338        /// Optional description
339        #[arg(long = "description")]
340        description: Option<String>,
341
342        /// Path to private key file for signing (PEM format)
343        #[arg(long = "key")]
344        key: Option<PathBuf>,
345
346        /// Hash algorithm to use for signing (default: sha384)
347        #[arg(long = "hash-alg", value_enum, default_value = "sha384")]
348        hash_alg: HashAlgorithmChoice,
349
350        /// Only print manifest without storing
351        #[arg(long = "print")]
352        print: bool,
353
354        /// Output encoding (json or cbor)
355        #[arg(long = "encoding", default_value = "json")]
356        encoding: String,
357
358        /// Storage backend (local or rekor)
359        #[arg(long = "storage-type", default_value = "database")]
360        storage_type: Box<String>,
361
362        /// Storage URL
363        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
364        storage_url: Box<String>,
365    },
366
367    /// List all evaluation results
368    List {
369        /// Storage backend (local or rekor)
370        #[arg(long = "storage-type", default_value = "database")]
371        storage_type: Box<String>,
372
373        /// Storage URL
374        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
375        storage_url: Box<String>,
376    },
377
378    /// Verify an evaluation result manifest
379    Verify {
380        /// Evaluation result manifest ID to verify
381        #[arg(long = "id")]
382        id: String,
383
384        /// Storage backend (local or rekor)
385        #[arg(long = "storage-type", default_value = "database")]
386        storage_type: Box<String>,
387
388        /// Storage URL
389        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
390        storage_url: Box<String>,
391    },
392}
393
394/// CCAttestationCommands are mostly for debugging since CC attestations
395/// will be collected directly during asset creation/modification
396#[derive(Subcommand)]
397pub enum CCAttestationCommands {
398    /// Reads the CC attestation and display it
399    Show,
400    /// Extracts the VM launch measurement value from the CC attestation
401    GetLaunchMeasurement,
402    /// Verify VM launch measurement against a launch endorsement
403    VerifyLaunch {
404        /// VM host platform (determines download command and format)
405        #[arg(long = "host-platform", default_value = "gcp-tdx")]
406        host_platform: String,
407    },
408}
409
410#[derive(Debug, Subcommand)]
411pub enum SoftwareCommands {
412    /// Create a new software component manifest
413    Create {
414        #[arg(long = "paths", num_args = 1.., value_delimiter = ',')]
415        paths: Vec<PathBuf>,
416
417        /// Names for each component (comma-separated)
418        #[arg(long = "ingredient-names", num_args = 1.., value_delimiter = ',')]
419        ingredient_names: Vec<String>,
420
421        /// Software name
422        #[arg(long = "name")]
423        name: String,
424
425        /// Software type (script, container, VM, etc.)
426        #[arg(long = "software-type")]
427        software_type: String,
428
429        /// Software version
430        #[arg(long = "version")]
431        version: Option<String>,
432
433        /// Author organization name
434        #[arg(long = "author-org")]
435        author_org: Option<String>,
436
437        /// Author name
438        #[arg(long = "author-name")]
439        author_name: Option<String>,
440
441        /// Optional description
442        #[arg(long = "description")]
443        description: Option<String>,
444
445        /// Optional linked manifest IDs
446        #[arg(long = "linked-manifests")]
447        linked_manifests: Option<Vec<String>>,
448
449        /// Path to private key file for signing (PEM format)
450        #[arg(long = "key")]
451        key: Option<PathBuf>,
452
453        /// Hash algorithm to use for signing (default: sha384)
454        #[arg(long = "hash-alg", value_enum, default_value = "sha384")]
455        hash_alg: HashAlgorithmChoice,
456
457        /// Only print manifest without storing
458        #[arg(long = "print")]
459        print: bool,
460
461        /// Output encoding (json or cbor)
462        #[arg(long = "encoding", default_value = "json")]
463        encoding: String,
464
465        /// Storage backend (local or rekor)
466        #[arg(long = "storage-type", default_value = "database")]
467        storage_type: Box<String>,
468
469        /// Storage URL
470        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
471        storage_url: Box<String>,
472
473        /// Collect the underlying CC attestation, if available
474        #[arg(long = "with-tdx", default_value = "false")]
475        with_tdx: bool,
476    },
477    /// List all software component manifests
478    List {
479        /// Storage backend (local or rekor)
480        #[arg(long = "storage-type", default_value = "database")]
481        storage_type: Box<String>,
482
483        /// Storage URL
484        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
485        storage_url: Box<String>,
486    },
487    /// Verify a software component manifest
488    Verify {
489        /// Manifest ID to verify
490        #[arg(long = "id")]
491        id: String,
492        /// Storage backend (local or rekor)
493        #[arg(long = "storage-type", default_value = "database")]
494        storage_type: Box<String>,
495
496        /// Storage URL
497        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
498        storage_url: Box<String>,
499    },
500    /// Link software to a model
501    LinkModel {
502        /// Software manifest ID
503        #[arg(long = "software-id")]
504        software_id: String,
505
506        /// Model manifest ID
507        #[arg(long = "model-id")]
508        model_id: String,
509
510        /// Storage backend (local or rekor)
511        #[arg(long = "storage-type", default_value = "database")]
512        storage_type: Box<String>,
513
514        /// Storage URL
515        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
516        storage_url: Box<String>,
517    },
518    /// Link software to a dataset
519    LinkDataset {
520        /// Software manifest ID
521        #[arg(long = "software-id")]
522        software_id: String,
523
524        /// Dataset manifest ID
525        #[arg(long = "dataset-id")]
526        dataset_id: String,
527
528        /// Storage backend (local or rekor)
529        #[arg(long = "storage-type", default_value = "database")]
530        storage_type: Box<String>,
531
532        /// Storage URL
533        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
534        storage_url: Box<String>,
535    },
536}
537
538#[derive(Debug, Subcommand)]
539pub enum PipelineCommands {
540    /// Generate SLSA Build Provenance v1 for the given pipeline
541    GenerateProvenance {
542        /// Paths to any pipeline inputs and other external parameters
543        #[arg(long = "inputs", num_args = 1.., value_delimiter = ',')]
544        inputs: Vec<PathBuf>,
545
546        /// Path to pipeline script or configuration
547        #[arg(long = "pipeline")]
548        pipeline: PathBuf,
549
550        /// Paths to any pipeline products
551        #[arg(long = "products", num_args = 1.., value_delimiter = ',')]
552        products: Vec<PathBuf>,
553
554        /// Path to private key file for signing (PEM format)
555        #[arg(long = "key")]
556        key: Option<PathBuf>,
557
558        /// Hash algorithm to use for signing (default: sha384)
559        #[arg(long = "hash-alg", value_enum, default_value = "sha384")]
560        hash_alg: HashAlgorithmChoice,
561
562        /// Only print SLSA Provenance without storing
563        #[arg(long = "print")]
564        print: bool,
565
566        /// Output encoding (json or cbor)
567        #[arg(long = "encoding", default_value = "json")]
568        encoding: String,
569
570        /// Storage backend (only local supported)
571        #[arg(long = "storage-type", default_value = "local-fs")]
572        storage_type: Box<String>,
573
574        /// Storage URL
575        #[arg(long = "storage-url", default_value = "http://localhost:8080")]
576        storage_url: Box<String>,
577
578        /// Collect the underlying TDX attestation, if available
579        #[arg(long = "with-tdx", default_value = "false")]
580        with_tdx: bool,
581    },
582}