legion-crypt 1.4.20 → 1.4.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b78a171584f4ccb627b63cd35cad927a6773bd1802e0da432dd445dbceb85e4
4
- data.tar.gz: b1806202e526aa259d1491a108f3d3b94b1c4564a05ea7b4afa702778069e715
3
+ metadata.gz: bc1b26f800d0d5512ee35965b6700750bcfcacc5265042f749c3e56a973140c6
4
+ data.tar.gz: cb154b6f1c44688b9a7d4d41e4c125279c9c945b8b162da448c1b2f7b0bacb67
5
5
  SHA512:
6
- metadata.gz: a1cc01154f5fef732c05efe2d99213f1742aa486e2c703f7707709dbf29ab74484b49e5be4c3a1513b116ffdb658382b70e124067771549f9dcabd8cad1fd6f1
7
- data.tar.gz: e8e674be70714e3d439330e8d1d03b323319dd60b0f2069c26087fa772ec27c61cbc3a1ca5ed47cdff30e5ee8a826e31f16b0695f35c479184be7a02fd34e2b7
6
+ metadata.gz: 4bf5a0be9d6c724dc0011508e7ce3ab23a8a9af46c7800fdd8a45711fa75e3569635bec16467d942306124c17c3a14c45bd161082b0e1c62a80c6172e9f050d9
7
+ data.tar.gz: cd5269888634c81cda229646c13db9a61a67c687430bda6b5202047a73f84fb480b55e1e39534fcadec348b34ee62f0c913723338b20c3ffba6e31943fa38922
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Legion::Crypt
2
2
 
3
+ ## [1.4.23] - 2026-03-27
4
+
5
+ ### Fixed
6
+ - `connect_vault` now accepts Vault standby responses (429, 472, 473) as healthy, fixing connection failures against performance standby nodes
7
+ - `connect_all_clusters` uses the same standby-tolerant health check
8
+
9
+ ## [1.4.22] - 2026-03-27
10
+
11
+ ### Changed
12
+ - Replace split `log.error(e.message); log.error(e.backtrace)` patterns with single `Legion::Logging.log_exception` calls in `vault.rb`, `cluster_secret.rb`, and `settings.rb` for structured exception events
13
+ - Guard all `log_exception` call sites in `vault.rb`, `settings.rb`, and `cluster_secret.rb` with `Legion::Logging` presence checks (`defined?` in `vault.rb`/`cluster_secret.rb`, `Legion.const_defined?('Logging')` in `settings.rb`) plus `Legion::Logging.respond_to?(:log_exception)`; fall back to `Legion::Logging.fatal`/`error` or `warn` to preserve structured logging in environments where `log_exception` is unavailable
14
+ - `from_transport` and `cs` rescue blocks in `cluster_secret.rb` now use the same 4-branch guard (log_exception / Logging.error / Logging.warn / Kernel.warn) and explicitly return `nil` to preserve expected return types
15
+ - Fallback `.error`/`.warn`/`Kernel.warn` branches in `from_transport` and `cs` include the first 10 backtrace lines for debuggability parity with the prior `e.backtrace[0..10]` logging; `Vault#connect_vault` warn fallback omits backtrace to keep health-check failure messages concise
16
+ - `cs` rescue adds final `Kernel.warn` fallback so exceptions are never silently swallowed when `Legion::Logging` is absent
17
+
18
+ ### Added
19
+ - Specs for `connect_vault` rescue logging: asserts `false` return and covers log_exception / Logging.error / warn fallback branches when `Vault.sys.health_status` raises
20
+ - Specs for `from_transport` and `cs` rescue paths: asserts `nil` return and covers all logging fallback branches (including `Kernel.warn`) plus `Legion::Logging` absent case
21
+ - Duplicate invocation eliminated in rescue-path specs: single call stored in `result`, both no-raise and return value asserted on that one call
22
+
3
23
  ## [1.4.20] - 2026-03-27
4
24
 
5
25
  ### Fixed
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Encryption, secrets management, JWT token management, and HashiCorp Vault integration for the [LegionIO](https://github.com/LegionIO/LegionIO) framework. Provides AES-256-CBC message encryption, RSA key pair generation, cluster secret management, JWT issue/verify operations, Vault token lifecycle management, and multi-cluster Vault connectivity.
4
4
 
5
- **Version**: 1.4.15
5
+ **Version**: 1.4.22
6
6
 
7
7
  ## Installation
8
8
 
@@ -64,8 +64,14 @@ module Legion
64
64
  Legion::Logging.error 'Cluster secret is still unknown!'
65
65
  nil
66
66
  rescue StandardError => e
67
- Legion::Logging.error e.message
68
- Legion::Logging.error e.backtrace[0..10]
67
+ if defined?(Legion::Logging) && Legion::Logging.respond_to?(:log_exception)
68
+ Legion::Logging.log_exception(e, lex: 'crypt', component_type: :helper)
69
+ elsif defined?(Legion::Logging) && Legion::Logging.respond_to?(:error)
70
+ Legion::Logging.error "from_transport failed: #{e.class}=#{e.message}\n#{Array(e.backtrace).first(10).join("\n")}"
71
+ else
72
+ warn "from_transport failed: #{e.class}=#{e.message}\n#{Array(e.backtrace).first(10).join("\n")}"
73
+ end
74
+ nil
69
75
  end
70
76
 
71
77
  def force_cluster_secret
@@ -114,8 +120,19 @@ module Legion
114
120
  def cs
115
121
  @cs ||= Digest::SHA256.digest(find_cluster_secret)
116
122
  rescue StandardError => e
117
- Legion::Logging.error e.message
118
- Legion::Logging.error e.backtrace[0..10]
123
+ if defined?(Legion::Logging) && Legion::Logging.respond_to?(:log_exception)
124
+ Legion::Logging.log_exception(e, lex: 'crypt', component_type: :helper)
125
+ elsif defined?(Legion::Logging) && Legion::Logging.respond_to?(:error)
126
+ backtrace = Array(e.backtrace).first(10).join("\n")
127
+ Legion::Logging.error "Legion::Crypt::ClusterSecret#cs failed: #{e.class}: #{e.message}\n#{backtrace}"
128
+ elsif defined?(Legion::Logging) && Legion::Logging.respond_to?(:warn)
129
+ backtrace = Array(e.backtrace).first(10).join("\n")
130
+ Legion::Logging.warn "Legion::Crypt::ClusterSecret#cs failed: #{e.class}: #{e.message}\n#{backtrace}"
131
+ else
132
+ backtrace = Array(e.backtrace).first(10).join("\n")
133
+ ::Kernel.warn "Legion::Crypt::ClusterSecret#cs failed: #{e.class}: #{e.message}\n#{backtrace}"
134
+ end
135
+ nil
119
136
  end
120
137
 
121
138
  def validate_hex(value, length = secret_length)
@@ -67,9 +67,10 @@ end
67
67
  begin
68
68
  Legion::Settings.merge_settings('crypt', Legion::Crypt::Settings.default) if Legion.const_defined?('Settings')
69
69
  rescue StandardError => e
70
- if Legion.const_defined?('Logging') && Legion::Logging.method_defined?(:fatal)
71
- Legion::Logging.fatal(e.message)
72
- Legion::Logging.fatal(e.backtrace)
70
+ if Legion.const_defined?('Logging') && Legion::Logging.respond_to?(:log_exception)
71
+ Legion::Logging.log_exception(e, lex: 'crypt', component_type: :helper, level: :fatal)
72
+ elsif Legion.const_defined?('Logging') && Legion::Logging.respond_to?(:fatal)
73
+ Legion::Logging.fatal("crypt settings merge error: #{e.class}: #{e.message}\n#{Array(e.backtrace).join("\n")}")
73
74
  else
74
75
  puts e.message
75
76
  puts e.backtrace
@@ -32,16 +32,32 @@ module Legion
32
32
  return nil if Legion::Settings[:crypt][:vault][:token].nil?
33
33
 
34
34
  ::Vault.token = Legion::Settings[:crypt][:vault][:token]
35
- if ::Vault.sys.health_status.initialized?
35
+ if vault_healthy?
36
36
  Legion::Settings[:crypt][:vault][:connected] = true
37
37
  Legion::Logging.info "Vault connected at #{::Vault.address}" if defined?(Legion::Logging)
38
38
  end
39
39
  rescue StandardError => e
40
- Legion::Logging.error e.message
40
+ if defined?(Legion::Logging) && Legion::Logging.respond_to?(:log_exception)
41
+ Legion::Logging.log_exception(e, lex: 'crypt', component_type: :helper)
42
+ elsif defined?(Legion::Logging) && Legion::Logging.respond_to?(:error)
43
+ Legion::Logging.error "Vault connection failed: #{e.class}=#{e.message}\n#{Array(e.backtrace).first(10).join("\n")}"
44
+ else
45
+ warn "Vault connection failed: #{e.class}=#{e.message}"
46
+ end
41
47
  Legion::Settings[:crypt][:vault][:connected] = false
42
48
  false
43
49
  end
44
50
 
51
+ def vault_healthy?
52
+ ::Vault.sys.health_status.initialized?
53
+ rescue ::Vault::HTTPError => e
54
+ # 429 = standby, 472 = DR secondary, 473 = performance standby
55
+ # All indicate an initialized, healthy Vault — just not the active node.
56
+ return true if e.message =~ /\b(429|472|473)\b/
57
+
58
+ raise
59
+ end
60
+
45
61
  def read(path, type = 'legion')
46
62
  full_path = type.nil? || type.empty? ? "#{type}/#{path}" : path
47
63
  log_read_context(full_path)
@@ -53,7 +53,7 @@ module Legion
53
53
  next unless config[:token]
54
54
 
55
55
  client = vault_client(name)
56
- config[:connected] = client.sys.health_status.initialized?
56
+ config[:connected] = cluster_healthy?(client)
57
57
  results[name] = config[:connected]
58
58
  log_cluster_connected(name, config) if config[:connected]
59
59
  end
@@ -71,6 +71,14 @@ module Legion
71
71
 
72
72
  private
73
73
 
74
+ def cluster_healthy?(client)
75
+ client.sys.health_status.initialized?
76
+ rescue ::Vault::HTTPError => e
77
+ return true if e.message =~ /\b(429|472|473)\b/
78
+
79
+ raise
80
+ end
81
+
74
82
  def mark_vault_connected
75
83
  return unless defined?(Legion::Settings)
76
84
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Crypt
5
- VERSION = '1.4.20'
5
+ VERSION = '1.4.23'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-crypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.20
4
+ version: 1.4.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity