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 =
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)
Validates that the file has strict 0600 permissions.
Class Method Details
.from_env(env_key) ⇒ String?
Reads a secret from the environment.
28 29 30 31 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 28 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.
37 38 39 40 41 42 43 44 45 46 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 37 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
62 63 64 65 66 67 68 69 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 62 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).
20 21 22 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 20 def resolve(env_key) from_env(env_key) || from_secrets_file(env_key) || raise_missing(env_key) end |
.validate_permissions!(path)
This method returns an undefined value.
Validates that the file has strict 0600 permissions.
53 54 55 56 57 58 59 60 |
# File 'lib/rosett_ai/secrets_resolver.rb', line 53 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 |