systemprompt_config/bootstrap/secrets/
error.rs1use systemprompt_manifest::profile::ProfileError;
7use systemprompt_models::errors::SecretsError;
8
9use super::vault::VaultError;
10use crate::bootstrap::key_material::KeyMaterialError;
11
12#[derive(Debug, thiserror::Error)]
13#[non_exhaustive]
14pub enum SecretsBootstrapError {
15 #[error(
16 "Secrets not initialized. Call SecretsBootstrap::init() after ProfileBootstrap::init()"
17 )]
18 NotInitialized,
19
20 #[error("Secrets already initialized")]
21 AlreadyInitialized,
22
23 #[error("Profile not initialized. Call ProfileBootstrap::init() first")]
24 ProfileNotInitialized,
25
26 #[error("Secrets file not found: {path}")]
27 FileNotFound { path: String },
28
29 #[error("Invalid secrets file: {0}")]
30 InvalidSecretsFile(#[source] SecretsError),
31
32 #[error("Secrets document could not be encoded: {0}")]
33 DocumentEncode(#[source] serde_json::Error),
34
35 #[error("No secrets configured. Create a secrets.json file.")]
36 NoSecretsConfigured,
37
38 #[error("Invalid secrets configuration in profile: {0}")]
39 SecretsConfigInvalid(#[source] ProfileError),
40
41 #[error(
42 "secrets.source is 'vault' but the profile has no secrets.vault block. Add one or switch \
43 secrets.source to 'file' or 'env'."
44 )]
45 VaultBlockMissing,
46
47 #[error(transparent)]
48 Vault(#[from] VaultError),
49
50 #[error(
51 "OAuth at-rest pepper is required. Add 'oauth_at_rest_pepper' (>= 32 chars) to your \
52 secrets file or set OAUTH_AT_REST_PEPPER environment variable."
53 )]
54 OauthAtRestPepperRequired,
55
56 #[error(
57 "Database URL is required. Add 'database_url' to your secrets.json or set DATABASE_URL \
58 environment variable."
59 )]
60 DatabaseUrlRequired,
61
62 #[error(
63 "manifest_signing_secret_seed is required: every replica must share one seed, so it is \
64 never generated at boot. Run `systemprompt admin identity generate --json` once and \
65 distribute the value (secrets file or MANIFEST_SIGNING_SECRET_SEED)."
66 )]
67 ManifestSeedRequired,
68
69 #[error(
70 "signing_key_pem is required on cloud and deployment-host boots: every replica must \
71 sign with one key, so it is never read from a file beside the binary there. Run \
72 `systemprompt admin identity generate --json` once and distribute the value (secrets \
73 file or SIGNING_KEY_PEM)."
74 )]
75 SigningKeyPemRequired,
76
77 #[error("manifest_signing_secret_seed is invalid: {0}")]
78 ManifestSeedInvalid(#[source] KeyMaterialError),
79
80 #[error(
81 "encryption_master_key is required: it seals at-rest secrets and the gateway accounting \
82 journal. Add 64 hex characters (`openssl rand -hex 32`) as 'encryption_master_key' in \
83 secrets.json, or take the value from `systemprompt admin identity generate`. With \
84 `secrets.source: env`, also list it in SYSTEMPROMPT_CUSTOM_SECRETS."
85 )]
86 EncryptionMasterKeyRequired,
87
88 #[error(
89 "encryption_master_key is invalid ({0}): it must be 32 bytes as 64 hex characters \
90 (`openssl rand -hex 32`)"
91 )]
92 EncryptionMasterKeyInvalid(#[source] KeyMaterialError),
93
94 #[error("signing_key_pem secret is invalid: {0}")]
95 SigningKeyPemInvalid(#[source] KeyMaterialError),
96
97 #[error(
98 "secrets.source is 'external' but the profile has no secrets.external block. Add one or \
99 switch secrets.source to 'file', 'env' or 'vault'."
100 )]
101 ExternalBlockMissing,
102
103 #[error(
104 "secrets.external.kind '{kind}' is not registered in this binary (registered: {known:?})"
105 )]
106 UnknownExternalKind { kind: String, known: Vec<String> },
107
108 #[error("external secrets source '{kind}' failed: {source}")]
109 External {
110 kind: String,
111 #[source]
112 source: Box<dyn std::error::Error + Send + Sync>,
113 },
114
115 #[error(
116 "secrets reload rejected: '{key}' changed, and it is pinned for the life of the process. \
117 Restart to adopt a new value."
118 )]
119 ReloadRejected { key: String },
120}