Module: RosettAi::SecretsResolver
- Defined in:
- lib/rosett_ai/secrets_resolver.rb
Overview
Resolves secrets through an ordered fallback chain. Resolution order: ENV variable > secrets file (0600). System keyring support planned for GUI phase (P3).
Constant Summary collapse
- SAFE_PERMISSIONS =
Returns File permission mode for secrets files.
0o600
Class Method Summary collapse
-
.from_env(env_key) ⇒ String?
Reads a secret from the environment.
-
.from_secrets_file(env_key) ⇒ String?
Reads a secret from the secrets YAML file.
- .raise_missing(env_key) ⇒ Object
-
.resolve(env_key) ⇒ String
Resolves a secret through the fallback chain (ENV > secrets file).
-
.validate_permissions!(path) ⇒ void
Validates that the file has strict 0600 permissions.
Class Method Details
.from_env(env_key) ⇒ String?
Reads a secret from the environment.
29 30 31 32 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 29 def from_env(env_key) value = ENV.fetch(env_key, nil) value unless value.nil? || value.empty? end |
.from_secrets_file(env_key) ⇒ String?
Reads a secret from the secrets YAML file.
38 39 40 41 42 43 44 45 46 47 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 38 def from_secrets_file(env_key) secrets_path = RosettAi.paths.secrets_file.to_s return nil unless File.exist?(secrets_path) (secrets_path) data = RosettAi::YamlLoader.load_file(secrets_path) return nil unless data.is_a?(Hash) data[env_key] end |
.raise_missing(env_key) ⇒ Object
63 64 65 66 67 68 69 70 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 63 def raise_missing(env_key) secrets_path = RosettAi.paths.secrets_file raise RosettAi::Error, <<~MSG.chomp #{env_key} not found. Set it via one of: 1. export #{env_key}=<value> 2. Add '#{env_key}: <value>' to #{secrets_path} (chmod 600) MSG end |
.resolve(env_key) ⇒ String
Resolves a secret through the fallback chain (ENV > secrets file).
21 22 23 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 21 def resolve(env_key) from_env(env_key) || from_secrets_file(env_key) || raise_missing(env_key) end |
.validate_permissions!(path) ⇒ void
This method returns an undefined value.
Validates that the file has strict 0600 permissions.
54 55 56 57 58 59 60 61 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 54 def (path) mode = File.stat(path).mode & 0o777 return if mode == SAFE_PERMISSIONS raise RosettAi::Error, "Secrets file #{path} has insecure permissions #{format('%04o', mode)}. " \ "Expected 0600. Fix with: chmod 600 #{path}" end |