Module: BrainzLab::Vault

Defined in:
lib/brainzlab/vault.rb,
lib/brainzlab/vault/cache.rb,
lib/brainzlab/vault/client.rb,
lib/brainzlab/vault/provisioner.rb

Defined Under Namespace

Classes: Cache, Client, Provisioner

Class Method Summary collapse

Class Method Details

.cacheObject



244
245
246
# File 'lib/brainzlab/vault.rb', line 244

def cache
  @cache ||= Cache.new(BrainzLab.configuration.vault_cache_ttl)
end

.clear_cache!Object

Clear the secret cache



211
212
213
# File 'lib/brainzlab/vault.rb', line 211

def clear_cache!
  cache.clear!
end

.clientObject



240
241
242
# File 'lib/brainzlab/vault.rb', line 240

def client
  @client ||= Client.new(BrainzLab.configuration)
end

.delete(key) ⇒ Boolean

Delete (archive) a secret

Parameters:

  • key (String)

    The secret key

Returns:

  • (Boolean)

    True if successful



166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/brainzlab/vault.rb', line 166

def delete(key)
  return false unless enabled?

  ensure_provisioned!
  return false unless BrainzLab.configuration.vault_valid?

  result = client.delete(key)

  # Invalidate all environment caches for this key
  cache.delete_pattern("*:#{key}") if result && BrainzLab.configuration.vault_cache_enabled

  result
end

.ensure_provisioned!Object

INTERNAL ===



229
230
231
232
233
234
# File 'lib/brainzlab/vault.rb', line 229

def ensure_provisioned!
  return if @provisioned

  @provisioned = true
  provisioner.ensure_project!
end

.export(environment: nil, format: :json) ⇒ Hash, String

Export all secrets for an environment

Parameters:

  • environment (String, Symbol) (defaults to: nil)

    Environment to export

  • format (Symbol) (defaults to: :json)

    Output format (:json, :dotenv, :shell)

Returns:

  • (Hash, String)

    Exported secrets



184
185
186
187
188
189
190
191
192
# File 'lib/brainzlab/vault.rb', line 184

def export(environment: nil, format: :json)
  return {} unless enabled?

  ensure_provisioned!
  return {} unless BrainzLab.configuration.vault_valid?

  env = environment&.to_s || BrainzLab.configuration.environment
  client.export(environment: env, format: format)
end

.fetch(key, env_var: nil) ⇒ String?

Fetch a secret with automatic fallback

Parameters:

  • key (String)

    The secret key

  • env_var (String) (defaults to: nil)

    Environment variable to fall back to

Returns:

  • (String, nil)

    The secret value



198
199
200
201
202
203
204
205
206
207
208
# File 'lib/brainzlab/vault.rb', line 198

def fetch(key, env_var: nil)
  value = get(key)
  return value if value && !value.to_s.empty?

  # Fall back to environment variable
  if env_var
    ENV.fetch(env_var, nil)
  else
    ENV.fetch(key, nil)
  end
end

.get(key, environment: nil, default: nil) ⇒ String?

Get a secret value

Parameters:

  • key (String)

    The secret key

  • environment (String, Symbol) (defaults to: nil)

    Optional environment (defaults to current environment)

  • default (Object) (defaults to: nil)

    Default value if secret not found

Returns:

  • (String, nil)

    The secret value



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/brainzlab/vault.rb', line 106

def get(key, environment: nil, default: nil)
  return default unless enabled?

  ensure_provisioned!
  return default unless BrainzLab.configuration.vault_valid?

  env = environment&.to_s || BrainzLab.configuration.environment
  cache_key = "#{env}:#{key}"

  # Check cache first
  return cache.get(cache_key) if BrainzLab.configuration.vault_cache_enabled && cache.has?(cache_key)

  value = client.get(key, environment: env)

  if value.nil?
    default
  else
    cache.set(cache_key, value) if BrainzLab.configuration.vault_cache_enabled
    value
  end
end

.list(environment: nil) ⇒ Array<Hash>

List all secret keys

Parameters:

  • environment (String, Symbol) (defaults to: nil)

    Optional environment

Returns:

  • (Array<Hash>)

    List of secret metadata



153
154
155
156
157
158
159
160
161
# File 'lib/brainzlab/vault.rb', line 153

def list(environment: nil)
  return [] unless enabled?

  ensure_provisioned!
  return [] unless BrainzLab.configuration.vault_valid?

  env = environment&.to_s || BrainzLab.configuration.environment
  client.list(environment: env)
end

.load!(environment: nil, overwrite: false, provider_keys: true) ⇒ Hash

Load all secrets into ENV like dotenv This is the main method to use at app startup

Examples:

# In config/application.rb or an initializer
BrainzLab::Vault.load!

# Load with options
BrainzLab::Vault.load!(environment: :production, overwrite: true)

Parameters:

  • environment (String, Symbol) (defaults to: nil)

    Environment to load (defaults to current)

  • overwrite (Boolean) (defaults to: false)

    Whether to overwrite existing ENV vars (default: false)

  • provider_keys (Boolean) (defaults to: true)

    Also load provider keys like OPENAI_API_KEY (default: true)

Returns:

  • (Hash)

    The secrets that were loaded



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/brainzlab/vault.rb', line 25

def load!(environment: nil, overwrite: false, provider_keys: true)
  return {} unless enabled?

  ensure_provisioned!
  return {} unless BrainzLab.configuration.vault_valid?

  env = environment&.to_s || BrainzLab.configuration.environment
  loaded = {}

  # Load regular secrets
  secrets = export(environment: env, format: :json)
  secrets.each do |key, value|
    key_str = key.to_s
    next unless overwrite || !ENV.key?(key_str)

    ENV[key_str] = value.to_s
    loaded[key_str] = value
    BrainzLab.debug_log("[Vault] Loaded #{key_str}")
  end

  # Load provider keys (OpenAI, Anthropic, etc.)
  if provider_keys
    provider_secrets = load_provider_keys!(overwrite: overwrite)
    loaded.merge!(provider_secrets)
  end

  BrainzLab.debug_log("[Vault] Loaded #{loaded.size} secrets into ENV")
  loaded
rescue StandardError => e
  BrainzLab.debug_log("[Vault] Failed to load secrets: #{e.message}")
  {}
end

.load_provider_keys!(overwrite: false) ⇒ Hash

Load provider keys (API keys for LLMs, etc.) into ENV

Parameters:

  • overwrite (Boolean) (defaults to: false)

    Whether to overwrite existing ENV vars

Returns:

  • (Hash)

    Provider keys that were loaded



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/brainzlab/vault.rb', line 62

def load_provider_keys!(overwrite: false)
  return {} unless enabled? && BrainzLab.configuration.vault_valid?

  loaded = {}
  provider_keys = client.get_provider_keys

  provider_keys.each do |provider, key|
    env_var = "#{provider.to_s.upcase}_API_KEY"
    next unless overwrite || !ENV.key?(env_var)

    ENV[env_var] = key
    loaded[env_var] = key
    BrainzLab.debug_log("[Vault] Loaded provider key: #{env_var}")
  end

  loaded
rescue StandardError => e
  BrainzLab.debug_log("[Vault] Failed to load provider keys: #{e.message}")
  {}
end

.provider_key(provider, model_type: 'llm') ⇒ String?

Get a specific provider key

Parameters:

  • provider (String, Symbol)

    Provider name (openai, anthropic, etc.)

  • model_type (String) (defaults to: 'llm')

    Model type (llm, embedding, etc.)

Returns:

  • (String, nil)

    The API key



87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/brainzlab/vault.rb', line 87

def provider_key(provider, model_type: 'llm')
  return nil unless enabled?

  ensure_provisioned!
  return nil unless BrainzLab.configuration.vault_valid?

  # Check ENV first
  env_var = "#{provider.to_s.upcase}_API_KEY"
  return ENV[env_var] if ENV[env_var] && !ENV[env_var].empty?

  # Fetch from Vault
  client.get_provider_key(provider: provider.to_s, model_type: model_type)
end

.provisionerObject



236
237
238
# File 'lib/brainzlab/vault.rb', line 236

def provisioner
  @provisioner ||= Provisioner.new(BrainzLab.configuration)
end

.reset!Object



248
249
250
251
252
253
# File 'lib/brainzlab/vault.rb', line 248

def reset!
  @client = nil
  @provisioner = nil
  @cache = nil
  @provisioned = false
end

.set(key, value, environment: nil, description: nil, note: nil) ⇒ Boolean

Set a secret value

Parameters:

  • key (String)

    The secret key

  • value (String)

    The secret value

  • environment (String, Symbol) (defaults to: nil)

    Optional environment (defaults to current environment)

  • description (String) (defaults to: nil)

    Optional description

  • note (String) (defaults to: nil)

    Optional version note

Returns:

  • (Boolean)

    True if successful



135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/brainzlab/vault.rb', line 135

def set(key, value, environment: nil, description: nil, note: nil)
  return false unless enabled?

  ensure_provisioned!
  return false unless BrainzLab.configuration.vault_valid?

  env = environment&.to_s || BrainzLab.configuration.environment
  result = client.set(key, value, environment: env, description: description, note: note)

  # Invalidate cache
  cache.delete("#{env}:#{key}") if result && BrainzLab.configuration.vault_cache_enabled

  result
end

.warm_cache!(environment: nil) ⇒ Object

Warm the cache with all secrets



216
217
218
219
220
221
222
223
224
225
# File 'lib/brainzlab/vault.rb', line 216

def warm_cache!(environment: nil)
  return unless enabled? && BrainzLab.configuration.vault_cache_enabled

  env = environment&.to_s || BrainzLab.configuration.environment
  secrets = export(environment: env, format: :json)

  secrets.each do |key, value|
    cache.set("#{env}:#{key}", value)
  end
end