/ crates / auths-cli / src / errors / cli_error.rs
cli_error.rs
 1  //! Typed CLI error variants with actionable help text.
 2  
 3  /// Structured CLI errors with built-in suggestion and documentation links.
 4  #[derive(thiserror::Error, Debug)]
 5  pub enum CliError {
 6      #[error("key rotation failed — no pre-rotation commitment found")]
 7      NoPrerotationCommitment,
 8  
 9      #[error("identity not found — run `auths init` to create one")]
10      IdentityNotFound,
11  
12      #[error("keychain unavailable — set AUTHS_KEYCHAIN_BACKEND=file for headless environments")]
13      KeychainUnavailable,
14  
15      #[error("device key '{alias}' not found — import it first with `auths key import`")]
16      DeviceKeyNotFound { alias: String },
17  
18      #[error("passphrase required — set AUTHS_PASSPHRASE env var for CI environments")]
19      PassphraseRequired,
20  
21      #[error("attestation expired — issue a new one with `auths device link`")]
22      AttestationExpired,
23  
24      #[error("capability '{capability}' not granted — check device authorization policies")]
25      MissingCapability { capability: String },
26  }
27  
28  impl CliError {
29      /// Human-readable suggestion for how to recover from this error.
30      pub fn suggestion(&self) -> &str {
31          match self {
32              Self::NoPrerotationCommitment => {
33                  "Run: auths key precommit --next-key <path-to-next-pubkey>"
34              }
35              Self::IdentityNotFound => "Run: auths init",
36              Self::KeychainUnavailable => {
37                  "Set AUTHS_KEYCHAIN_BACKEND=file and AUTHS_PASSPHRASE=<passphrase> in your environment."
38              }
39              Self::DeviceKeyNotFound { .. } => "Run: auths key import --alias <alias> --file <path>",
40              Self::PassphraseRequired => {
41                  "Set AUTHS_PASSPHRASE=<your-passphrase> in the environment, or run interactively."
42              }
43              Self::AttestationExpired => "Run: auths device link --device-alias <name>",
44              Self::MissingCapability { .. } => {
45                  "Run: auths device link --capability <cap> to add the capability."
46              }
47          }
48      }
49  
50      /// Documentation URL for this error, if available.
51      ///
52      /// These URLs map to Markdown source files under `docs/guides/` in this repository
53      /// (e.g., `docs/guides/key-rotation.md`). Keep the slugs in sync with those filenames
54      /// so static site generators (e.g., mdBook, Docusaurus) can serve them correctly.
55      pub fn docs_url(&self) -> Option<&str> {
56          match self {
57              Self::NoPrerotationCommitment => Some("https://docs.auths.dev/guides/key-rotation"),
58              Self::IdentityNotFound => Some("https://docs.auths.dev/guides/getting-started"),
59              Self::KeychainUnavailable => Some("https://docs.auths.dev/guides/headless-setup"),
60              _ => None,
61          }
62      }
63  }