1use std::sync::Arc;
4
5#[derive(Debug, thiserror::Error, miette::Diagnostic, Clone)]
12#[non_exhaustive]
13pub enum UpdateError {
14 #[error(transparent)]
16 #[diagnostic(transparent)]
17 Provider(#[from] rtb_forge::ProviderError),
18
19 #[error("no asset found for target {target}")]
21 #[diagnostic(
22 code(rtb::update::no_matching_asset),
23 help("the release exists but has no asset for this platform; a rebuild may be needed")
24 )]
25 NoMatchingAsset {
26 target: String,
28 },
29
30 #[error("asset signature file missing (expected `{asset}.sig` or `{asset}.minisig`)")]
32 #[diagnostic(
33 code(rtb::update::missing_signature),
34 help(
35 "every published release must ship a detached signature; re-run the release pipeline"
36 )
37 )]
38 MissingSignature {
39 asset: String,
41 },
42
43 #[error("signature verification failed for `{asset}`")]
45 #[diagnostic(
46 code(rtb::update::bad_signature),
47 help(
48 "the downloaded bytes do not match the vendor's public key — treat as a potential tampering event"
49 )
50 )]
51 BadSignature {
52 asset: String,
54 },
55
56 #[error("SHA-256 checksum mismatch for `{asset}`")]
58 #[diagnostic(code(rtb::update::bad_checksum))]
59 BadChecksum {
60 asset: String,
62 },
63
64 #[error("downloaded binary failed the runnable-self-test")]
67 #[diagnostic(
68 code(rtb::update::self_test_failed),
69 help("the new binary refused `--version`; refusing to swap")
70 )]
71 SelfTestFailed,
72
73 #[error("atomic swap failed: {0}")]
75 #[diagnostic(code(rtb::update::swap_failed))]
76 SwapFailed(String),
77
78 #[error("tool metadata carries no release source; update disabled")]
81 #[diagnostic(code(rtb::update::no_source))]
82 NoReleaseSource,
83
84 #[error("no usable public key: every entry in the trust set failed to parse")]
91 #[diagnostic(
92 code(rtb::update::malformed_public_key),
93 help(
94 "`ToolMetadata::update_public_keys` takes minisign public keys — the base64 string from a minisign.pub, e.g. \"RWR…\""
95 )
96 )]
97 MalformedPublicKey,
98
99 #[error("tool metadata carries no public key; signatures cannot be verified")]
102 #[diagnostic(
103 code(rtb::update::no_public_key),
104 help("populate `ToolMetadata::update_public_keys` at compile time")
105 )]
106 NoPublicKey,
107
108 #[error("downgrade refused: target {target} is older than current {current}")]
112 #[diagnostic(
113 code(rtb::update::downgrade_refused),
114 help("pass `--force` to explicitly downgrade")
115 )]
116 DowngradeRefused {
117 target: semver::Version,
119 current: semver::Version,
121 },
122
123 #[error("archive extraction failed: {0}")]
125 #[diagnostic(code(rtb::update::archive))]
126 Archive(String),
127
128 #[error("asset pattern invalid or unmatched: {0}")]
131 #[diagnostic(code(rtb::update::pattern))]
132 Pattern(String),
133
134 #[error("I/O error: {0}")]
136 #[diagnostic(code(rtb::update::io))]
137 Io(#[from] Arc<std::io::Error>),
138}
139
140impl From<std::io::Error> for UpdateError {
141 fn from(err: std::io::Error) -> Self {
142 Self::Io(Arc::new(err))
143 }
144}
145
146pub type Result<T> = std::result::Result<T, UpdateError>;