quonfig-openfeature 2.1.0 → 2.3.0

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: cd942b88517b56c8ff6d676684e0f1c27fbd5fd62c96c15964af1239d0ac2fe6
4
- data.tar.gz: bff802046f4d1ec5c0422e93f7c13a28edeb98178f2703354511976dc4c3384e
3
+ metadata.gz: 43b628f81214e3ced11ab61bcce6a2a84d9dfe8abd1aaec2f90590466c8b5b5c
4
+ data.tar.gz: 53464b81651916ed49c83ed88a95a94829e278ccbff56bfaa5236c4e89ab56a0
5
5
  SHA512:
6
- metadata.gz: 57db850f4f8384be2cc8b47e690ff363876d9ab51a5c7e80468880b3cf9b4607b7263f9081b965feef1dc6cc3e3c0594180153cb67cf9a5317fb7025562e70a9
7
- data.tar.gz: 56bb8b4420465725dd15303de581c254abae3d5f27a98205463dbed394f9cc9848ae47c61d97f7ac89962d707fa35ae8ed6d8c05fb66c2f9e0a50050c434123f
6
+ metadata.gz: 2db151d762fa6ae6be9c4197790153deba4b3a083b66101d24524de19c19952fbe6ba247dbf70a3504137c7c9c66243d3f6a144e6a6f8e97ef015352dea484b8
7
+ data.tar.gz: f8434a2390cfd3d55848383562b874d2fd81e1353247df49c35262a76bed642e09d2adcca9c0fe5daf859fed4b3bd5c3c55321e661f9c997a2f19784feddc7f7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.3.0 - 2026-10-29
4
+
5
+ When sdk-ruby reports error code `PARSE_ERROR` for a value that did not parse (qfg-wg1n), the
6
+ provider now returns it as OpenFeature `PARSE_ERROR` in one read: your default, reason `ERROR`, and
7
+ the SDK's message, variant and flag metadata. Before, an SDK `PARSE_ERROR` came back as `GENERAL`.
8
+
9
+ Nothing changes with the sdk-ruby you run today. sdk-ruby 2.1.0 reports a malformed value as
10
+ `TYPE_MISMATCH`, and the provider still tells the two apart as in 2.1.0: it checks the stored
11
+ `valueType` and reads the config again with the getter for that type. The `quonfig` floor stays
12
+ `>= 2.1.0`.
13
+
14
+ ## 2.2.0 - 2026-10-29
15
+
16
+ `fetch_string_value` on a `duration` config returns its stored ISO 8601 text again (reason
17
+ `STATIC`), as in openfeature-go and the shared OpenFeature cases (qfg-177f). The text comes back
18
+ unchanged: `"PT90S"` stays `"PT90S"`, not `"PT1M30S"`. 2.x returned your default with
19
+ `TYPE_MISMATCH`. Number reads of a duration still return your default. A malformed stored duration
20
+ such as `"30s"` still returns your default with `PARSE_ERROR`, and so does a duration ENV_VAR set
21
+ to a malformed value.
22
+
23
+ Requires quonfig (sdk-ruby) 2.1.0: the text is read with its new public `evaluate_details`, in one
24
+ evaluation, and checked against the shared duration grammar with `Quonfig::Duration.valid?`.
25
+
3
26
  ## 2.1.0 - 2026-10-28
4
27
 
5
28
  A malformed value now resolves with error code `PARSE_ERROR` instead of `TYPE_MISMATCH`
data/README.md CHANGED
@@ -134,9 +134,9 @@ Quonfig features require the native `quonfig` SDK:
134
134
 
135
135
  1. **Log levels** -- `should_log?` and the `semantic_logger_filter` are native-only.
136
136
  2. **`string_list` configs** -- accessed via `fetch_object_value` and used as `Array<String>`.
137
- 3. **`duration` configs** -- native-only: read them with `provider.client.get_duration` (integer
138
- milliseconds). `fetch_float_value` and `fetch_number_value` on a duration config return your
139
- default with `TYPE_MISMATCH`.
137
+ 3. **`duration` configs** -- `fetch_string_value` returns the stored ISO 8601 text unchanged
138
+ (`"PT90S"`). For integer milliseconds use `provider.client.get_duration`. `fetch_float_value`
139
+ and `fetch_number_value` on a duration config return your default with `TYPE_MISMATCH`.
140
140
  4. **`bytes` configs** -- not accessible via OpenFeature (no binary type in OF).
141
141
  5. **`keys` / raw config inspection** -- native-only via `provider.client`.
142
142
  6. **Context keys use dot-notation** -- `"user.email"`, not nested hashes.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.0
1
+ 2.3.0
@@ -80,7 +80,12 @@ module Quonfig
80
80
  'string_list' => :get_string_list_details,
81
81
  'json' => :get_json_details
82
82
  }.freeze
83
- private_constant :READABLE_VALUE_TYPES, :NATIVE_DETAILS_GETTER
83
+ # sdk-ruby's error code for a value that did not parse (a malformed
84
+ # stored value or ENV_VAR value, qfg-wg1n). Matched as a string: the
85
+ # quonfig floor (2.1.0) defines no constant for it and never emits it,
86
+ # so with that SDK the TYPE_MISMATCH re-read in #malformed? still applies.
87
+ SDK_PARSE_ERROR = 'PARSE_ERROR'
88
+ private_constant :READABLE_VALUE_TYPES, :NATIVE_DETAILS_GETTER, :SDK_PARSE_ERROR
84
89
 
85
90
  attr_reader :metadata, :targeting_key_mapping
86
91
 
@@ -148,8 +153,12 @@ module Quonfig
148
153
  end
149
154
  end
150
155
 
156
+ # A +duration+ config reads as its stored ISO 8601 text, unchanged
157
+ # ("PT90S" stays "PT90S"): OpenFeature has no duration type (qfg-177f).
151
158
  def fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
152
159
  evaluate(flag_key, default_value, evaluation_context) do |client, mapped_ctx|
160
+ next duration_iso_resolution(client, flag_key, mapped_ctx, default_value) if stored_value_type(client, flag_key) == 'duration'
161
+
153
162
  details = client.get_string_details(flag_key, context: mapped_ctx)
154
163
  to_resolution(details, default_value, parse_error: malformed?(client, flag_key, mapped_ctx, :string, details))
155
164
  end
@@ -247,6 +256,38 @@ module Quonfig
247
256
  native.error_code == ::Quonfig::EvaluationDetails::ERROR_TYPE_MISMATCH
248
257
  end
249
258
 
259
+ # Read a duration config as its ISO 8601 text with one evaluation:
260
+ # sdk-ruby's evaluate_details (quonfig >= 2.1.0) returns the resolved
261
+ # value in stored form, so the text is the stored text, or an ENV_VAR's
262
+ # text for a provided duration. evaluate_details does no type check, so
263
+ # the text is validated here with Quonfig::Duration.valid?, the grammar
264
+ # get_duration uses:
265
+ #
266
+ # * valid text: the text, with the evaluation's reason, variant and
267
+ # flag_metadata.
268
+ # * malformed stored text ("30s"): the default with PARSE_ERROR.
269
+ # * malformed ENV_VAR: evaluate_details reports ERROR / TYPE_MISMATCH,
270
+ # which on a duration config can only mean a value that did not
271
+ # parse, so it is PARSE_ERROR too.
272
+ # * the structured { seconds, nanos } shape has no ISO text: the
273
+ # default with TYPE_MISMATCH.
274
+ def duration_iso_resolution(client, flag_key, mapped_ctx, default_value)
275
+ details = client.evaluate_details(flag_key, context: mapped_ctx)
276
+ if details.reason == ::Quonfig::EvaluationDetails::REASON_ERROR
277
+ parse_error = details.error_code == ::Quonfig::EvaluationDetails::ERROR_TYPE_MISMATCH
278
+ return to_resolution(details, default_value, parse_error: parse_error)
279
+ end
280
+ return to_resolution(details, default_value) if details.reason == ::Quonfig::EvaluationDetails::REASON_DEFAULT
281
+
282
+ value = details.value
283
+ return to_resolution(details, default_value) if value.is_a?(String) && ::Quonfig::Duration.valid?(value)
284
+
285
+ error_code = value.is_a?(String) ? ErrorCode::PARSE_ERROR : ErrorCode::TYPE_MISMATCH
286
+ ResolutionDetails.new(value: default_value, reason: Reason::ERROR, error_code: error_code,
287
+ error_message: "duration #{flag_key.inspect} has no valid ISO 8601 text",
288
+ variant: details.variant, flag_metadata: details.flag_metadata || {})
289
+ end
290
+
250
291
  def stored_value_type(client, flag_key)
251
292
  config = client.store.get(flag_key)
252
293
  return nil unless config.is_a?(Hash)
@@ -257,7 +298,8 @@ module Quonfig
257
298
  # Map a Quonfig::EvaluationDetails to the OpenFeature ResolutionDetails
258
299
  # the SDK consumes. The Quonfig SDK's *_details methods don't raise, so
259
300
  # this is a pure mapping layer. +parse_error+ reports an ERROR as
260
- # PARSE_ERROR (see #malformed?).
301
+ # PARSE_ERROR (see #malformed?); an SDK PARSE_ERROR passes straight
302
+ # through in #map_error_code.
261
303
  def to_resolution(details, default_value, parse_error: false)
262
304
  variant = details.variant
263
305
  flag_metadata = details.flag_metadata || {}
@@ -302,6 +344,7 @@ module Quonfig
302
344
  when ::Quonfig::EvaluationDetails::ERROR_FLAG_NOT_FOUND then ErrorCode::FLAG_NOT_FOUND
303
345
  when ::Quonfig::EvaluationDetails::ERROR_TYPE_MISMATCH then ErrorCode::TYPE_MISMATCH
304
346
  when ::Quonfig::EvaluationDetails::ERROR_PROVIDER_NOT_READY then ErrorCode::PROVIDER_NOT_READY
347
+ when SDK_PARSE_ERROR then ErrorCode::PARSE_ERROR
305
348
  else ErrorCode::GENERAL
306
349
  end
307
350
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quonfig-openfeature
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Dwyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-28 00:00:00.000000000 Z
11
+ date: 2026-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: openfeature-sdk
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 2.0.0
33
+ version: 2.1.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 2.0.0
40
+ version: 2.1.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement