legion-settings 1.4.4 → 1.4.5

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: 5b4ca4881211bedb39799998f075d8539d5ebfdf79178f2d6c61e9ee1ebd28db
4
- data.tar.gz: fcf3c214190e2263cb67e4d17c5f8ddaceb478e5fed16a9a8021ed2722e4d160
3
+ metadata.gz: bb5f0ea206885bc8fa9a712afd9a73795958698bd9cb4495d2ed96d041120f5a
4
+ data.tar.gz: b2473c65ec3dab1b7e2b0d9aeb71f6cb4c38ccebb16c68eec70320eabc8e14a1
5
5
  SHA512:
6
- metadata.gz: f3f2a51d7a7633bf404b5f965c374357abc4a70d5c9e8d69ebd1bee22dfd4b3c878a4ee3af9870d1a4d42fe471a973db3b9c765dca9fc835f105b8c6ecd8ce42
7
- data.tar.gz: 34a30b2ec19e8c310c89a5c59b1d2b87ad01fddd09d5948738c3092cd6c5d77d86384a25aa1884bbe44fc27db288e929c1db863d2ef46b126b7b4d045e5c124b
6
+ metadata.gz: 798a3499c214b6427873b30a3259bfa453c38a9cd144d45f99aa64bb98857ab6b9d41c5ced8e461929623116a467d5bf6a459d4f423adf7786ea0800709a6af0
7
+ data.tar.gz: 19545fafd3710ca2c08253557d2c70b519b74d7efc604566b092ed339f56b72d626a7f3b18d5ce4c9afe494d62ddd8cf4a343bf2d0a1a3b6eb87e129c8f19138
@@ -8,17 +8,17 @@ on:
8
8
 
9
9
  jobs:
10
10
  ci:
11
- uses: LegionIO/.github/.github/workflows/ci.yml@main
11
+ uses: LegionIO/.github/.github/workflows/ci.yml@e0fc7364b73f446d4cb9bdc162a66ed34bf0daa7
12
12
  with:
13
- companion-gems: ${{ github.event_name == 'pull_request' && '{"legion-crypt":{"repository":"LegionIO/legion-crypt","ref":"f22702285d9ad9d80ddab115cf93568583bd7211"}}' || '{}' }}
13
+ companion-gems: ${{ github.event_name == 'pull_request' && '{"legion-crypt":{"repository":"LegionIO/legion-crypt","ref":"9317bd69cbbcc0feeaaff8368bed3569ed98b101"}}' || '{}' }}
14
14
 
15
15
  lint:
16
16
  uses: LegionIO/.github/.github/workflows/lint-patterns.yml@main
17
17
 
18
18
  security:
19
- uses: LegionIO/.github/.github/workflows/security-scan.yml@main
19
+ uses: LegionIO/.github/.github/workflows/security-scan.yml@e0fc7364b73f446d4cb9bdc162a66ed34bf0daa7
20
20
  with:
21
- companion-gems: ${{ github.event_name == 'pull_request' && '{"legion-crypt":{"repository":"LegionIO/legion-crypt","ref":"f22702285d9ad9d80ddab115cf93568583bd7211"}}' || '{}' }}
21
+ companion-gems: ${{ github.event_name == 'pull_request' && '{"legion-crypt":{"repository":"LegionIO/legion-crypt","ref":"9317bd69cbbcc0feeaaff8368bed3569ed98b101"}}' || '{}' }}
22
22
 
23
23
  version-changelog:
24
24
  uses: LegionIO/.github/.github/workflows/version-changelog.yml@main
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Legion::Settings Changelog
2
2
 
3
+ ## [1.4.5] - 2026-11-01
4
+
5
+ ### Fixed
6
+ - Preserve explicitly configured arrays, including empty allowlists, when registering module or library defaults; never restore disabled entries from defaults.
7
+ - Retain registered module defaults across `load(force: true)` while allowing freshly loaded user configuration to remain authoritative.
8
+
3
9
  ## [1.4.4] - 2026-10-31
4
10
 
5
11
  ### Fixed
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  The process-local, in-memory settings store for the [LegionIO](https://github.com/LegionIO/LegionIO) framework. Loads settings from JSON files, directories, and environment variables into a shared settings tree, exposed through `Legion::Settings[:key]`.
4
4
 
5
- **Version**: 1.4.4
5
+ **Version**: 1.4.5
6
6
 
7
7
  ## Process-Local Settings Model
8
8
 
@@ -126,7 +126,7 @@ Array values act as fallback chains — the first non-nil result wins:
126
126
 
127
127
  Call `Legion::Settings.resolve_secrets!` to resolve all URIs in-place. In the LegionIO boot sequence this is called automatically after `Legion::Crypt.start`. The `env://` scheme works even when Vault is not connected.
128
128
 
129
- Lease integration requires **legion-crypt 1.5.38 or newer** with **legion-settings 1.4.4 or newer**. Release Crypt first. Neither gem gains a runtime dependency on the other; environment and literal-only resolution work without Crypt.
129
+ Lease integration requires **legion-crypt 1.5.38 or newer** with **legion-settings 1.4.4 or newer**. Settings keeps Crypt optional, so environment and literal-only resolution work without Crypt. Crypt 1.5.39 and newer require Settings as a runtime dependency.
130
130
 
131
131
  Only the winning lease in a fallback chain can rotate its destination. A winning environment, Vault, or literal value—including `false`—does not subscribe unused leases. Nested hashes and arrays use typed paths, so array indexes and keys containing dots are preserved.
132
132
 
@@ -155,11 +155,17 @@ Legion::Settings.validate! # raises ValidationError if any settings are invalid
155
155
 
156
156
  ### Library Defaults
157
157
 
158
- Libraries own their defaults and register them with
158
+ Libraries own their defaults and register them once at startup with
159
159
  `Legion::Settings.register_library(:my_library, defaults)`. Existing configuration
160
- values take precedence. Registration is idempotent for the active loader; after
161
- replacing the loader or calling `load(force: true)`, a library can register its
162
- defaults again without losing configuration overrides.
160
+ values take precedence, including `false`, `nil`, and empty or restricted arrays.
161
+ Registration fills missing keys; it does not union default arrays into user policy.
162
+ `load(force: true)` retains registered defaults and applies them after loading user
163
+ configuration. A manually replaced loader must be bootstrapped explicitly.
164
+
165
+ Consumers read live `Legion::Settings[:component][:key]` values instead of caching
166
+ loader pointers or registering defaults during reads. LegionIO automatically injects
167
+ `Legion::Settings::Helper` into framework runners and actors; those consumers use
168
+ their native `settings[:key]` helper.
163
169
 
164
170
  Settings and overlays are local to the process. Registration does not synchronize
165
171
  configuration across processes or provide durable shared state.
@@ -48,6 +48,29 @@ module Legion
48
48
  end
49
49
  base
50
50
  end
51
+
52
+ # Defaults fill missing keys; configured scalars and arrays remain authoritative.
53
+ def merge_defaults(defaults:, settings:)
54
+ defaults.each_with_object(settings.dup) do |(key, value), merged|
55
+ if !settings.key?(key)
56
+ merged[key] = duplicate_default(value: value)
57
+ elsif value.is_a?(Hash) && settings[key].is_a?(Hash)
58
+ merged[key] = merge_defaults(defaults: value, settings: settings[key])
59
+ end
60
+ end
61
+ end
62
+
63
+ def duplicate_default(value:)
64
+ case value
65
+ when Hash
66
+ value.transform_values { |child| duplicate_default(value: child) }
67
+ when Array
68
+ value.map { |child| duplicate_default(value: child) }
69
+ else
70
+ value.dup
71
+ end
72
+ end
73
+ private_class_method :duplicate_default
51
74
  end
52
75
  end
53
76
  end
@@ -215,14 +215,14 @@ module Legion
215
215
  mod_name = config.keys.first
216
216
  log.debug("Loading module settings: #{mod_name}")
217
217
  @merged_modules = deep_merge(@merged_modules, config)
218
- @settings = deep_merge(config, @settings)
218
+ @settings = DeepMerge.merge_defaults(defaults: config, settings: @settings)
219
219
  mark_dirty!
220
220
  end
221
221
 
222
222
  def load_module_default(config)
223
223
  mod_name = config.keys.first
224
224
  log.debug("Loading module defaults: #{mod_name}")
225
- @settings = deep_merge(config, @settings)
225
+ @settings = DeepMerge.merge_defaults(defaults: config, settings: @settings)
226
226
  mark_dirty!
227
227
  end
228
228
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Settings
5
- VERSION = '1.4.4'
5
+ VERSION = '1.4.5'
6
6
  end
7
7
  end
@@ -30,6 +30,7 @@ module Legion
30
30
 
31
31
  # Create Loader once; reuse for subsequent calls (preserves module merges)
32
32
  if @loader.nil? || options[:force]
33
+ module_defaults = @loader&.merged_modules
33
34
  @loader = Legion::Settings::Loader.new
34
35
  @loader.load_env
35
36
  @loader.load_dns_bootstrap
@@ -40,6 +41,7 @@ module Legion
40
41
  options[:config_dirs]&.each do |directory|
41
42
  @loader.load_directory(directory)
42
43
  end
44
+ @loader.load_module_settings(module_defaults) if module_defaults
43
45
 
44
46
  @loaded = true if has_config
45
47
  load_project_env
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-settings
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.4
4
+ version: 1.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity