quonfig 1.2.0 → 1.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: d9da26b9a9f898ec76bf8520043abc42db011adf5e298cffa16ee8764c2c0ed6
4
- data.tar.gz: '0189ef6ee1e93cec985f9f5b1f1b81f833527bf3c22a1af7886778d8f2dcb50e'
3
+ metadata.gz: 8408e71b66de6bfe3e771b4091429d31f15f1dbdc0bb74d2e05bc3bcd83415db
4
+ data.tar.gz: e22b82909ffbb87dec181aa5c526ae12f7d4d7669c498027809ba8209ccd7c97
5
5
  SHA512:
6
- metadata.gz: e363cf1a35bbc428f35d1d4cebea4223dc84c4a1ddd39c3a7dcbc22bafb58a757b5fde92f357dd1a9b8c0e0cc90db247addd88c873e19887cd1d0eae0bc5332b
7
- data.tar.gz: e81f8441d30449624e3c64b506e113d386ce8a55656943e4523cb2d919d97aad5d8afd68df6462df1324cb2368dd8d9694e808146d622dd790ccf722e630e442
6
+ metadata.gz: '0149ee240869602465f2ff10180f8f2c35b577bf12d6f73bf33afe02ac16e0742e93744c085cbd641c1640b542a137dbde8650e5dde580174b718d89d4b08ed6'
7
+ data.tar.gz: b223c20dc4cde206a30e803d43d507c1e4b5f204465c7e5e0c1f19db178842bc3a5013db7d734d09178a23cddca3df4e2b275f4f000b71bb3f2566e6395d337d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.3.0 - 2026-08-18
4
+
5
+ > **Heads up — datadir users will start emitting telemetry.** Datadir mode with a valid SDK key now emits usage telemetry as documented; it previously sent nothing. If you run the SDK with a `datadir:` (or `QUONFIG_DIR`) **and** an SDK key, upgrading to 1.3.0 means evaluation summaries and context telemetry begin flowing to the telemetry service from that deployment — data you were not sending on 1.2.0. Disable with the standard telemetry options if unwanted (`collect_evaluation_summaries: false` and `context_upload_mode: :none`). A datadir client with **no** SDK key still sends nothing at all.
6
+
7
+ - **Fix (telemetry): the telemetry gate is SDK-key presence, not delivery mode (qfg-5x9x).** `Options#telemetry_allowed?` consulted `local_only?` (i.e. "is a datadir set?"), which forced every `collect_max_*` to `0` the moment a datadir was configured. With no collector limits the client built no aggregators, took `initialize_telemetry`'s early return, and never constructed a `TelemetryReporter` — so a datadir client holding a perfectly valid SDK key emitted **no** evaluation summaries, **no** context telemetry, nothing at all. Datadir is a config-**delivery** mode: it decides where config comes from, not whether usage is reported. The gate is now the SDK key alone, which is what identifies the workspace telemetry is attributed to. This aligns sdk-ruby with sdk-node, sdk-go, sdk-python, sdk-java, and sdk-net, and is the inverse of the defect fixed for sdk-go / sdk-python in 1.2.1 (those *over*-sent without a key). No wire-format change, no new dependencies, no public API removed.
8
+ - **Fix (telemetry): a keyless client now collects nothing at all.** Without an SDK key there is no workspace to attribute telemetry to, so the aggregators are no longer even allocated and the reporter never starts (previously the collectors filled up in delivery mode and were discarded at flush time). Behavior for the open-source / no-account path is unchanged from the outside — still zero telemetry HTTP — but nothing is accumulated in memory on the way there.
9
+ - **Deprecated: `allow_telemetry_in_local_mode:` is now a no-op.** It existed only to re-enable telemetry that datadir mode had suppressed; with mode out of the decision there is nothing left for it to unlock. The kwarg is still accepted so existing callers keep working, and it can neither enable telemetry without a key nor suppress it with one. Slated for removal in 2.0.0 — use `collect_evaluation_summaries: false` / `context_upload_mode: :none` to opt out.
10
+ - **Docs:** the README's datadir section previously claimed the mode "performs no network I/O" unconditionally. It now states the delivery-side guarantee precisely (no config fetch, no SSE, no polling) and documents the telemetry gate, including how to run datadir + key with telemetry off.
11
+
3
12
  ## 1.2.0 - 2026-07-08
4
13
 
5
14
  - **Feat (options): warn when an explicit `api_urls` disables automatic failover (qfg-41nh.26).** The default (and every `QUONFIG_DOMAIN`-derived) `api_urls` list carries a primary AND a secondary leg, and the HTTP config-fetch hedges/fails over between them (the secondary runs on separate infrastructure). An explicit `api_urls:` replaces that list wholesale, so a single-entry override silently dropped the secondary and disabled automatic failover. The client now logs one WARN at init when the caller explicitly set `api_urls` and the resolved list has fewer than two legs, pointing at the fix (pass both a primary and a secondary URL). Behavior is otherwise unchanged; no new dependencies. A new README "Failover & `QUONFIG_DOMAIN`" section documents the URL derivation and the failover model.
data/README.md CHANGED
@@ -86,7 +86,8 @@ bound.get_int('rate-limit')
86
86
 
87
87
  For tests, CI, or air-gapped environments, point the client at a local workspace
88
88
  directory instead of the Quonfig API. In datadir mode the SDK loads JSON config
89
- files from disk and performs no network I/O.
89
+ files from disk config delivery does no network I/O at all: no config fetch,
90
+ no SSE stream, no polling.
90
91
 
91
92
  ```ruby
92
93
  client = Quonfig::Client.new(
@@ -111,6 +112,32 @@ export QUONFIG_ENVIRONMENT=production
111
112
  client = Quonfig::Client.new # reads QUONFIG_DIR + QUONFIG_ENVIRONMENT
112
113
  ```
113
114
 
115
+ ### Telemetry in datadir mode
116
+
117
+ Usage telemetry is gated on **SDK-key presence, not on mode**. A datadir client
118
+ with an `sdk_key:` configured still reports evaluation summaries and context
119
+ telemetry to the telemetry service, exactly as a delivery-mode client does —
120
+ that combination is what makes flag usage visible in the Quonfig UI for services
121
+ that read config from a checked-out workspace.
122
+
123
+ A datadir client with **no** SDK key has no workspace to attribute telemetry to,
124
+ so it collects and sends nothing: fully offline, zero network I/O.
125
+
126
+ To run with a key but without telemetry, use the standard opt-outs:
127
+
128
+ ```ruby
129
+ client = Quonfig::Client.new(
130
+ datadir: '/path/to/workspace',
131
+ environment: 'production',
132
+ sdk_key: ENV['QUONFIG_BACKEND_SDK_KEY'],
133
+ collect_evaluation_summaries: false,
134
+ context_upload_mode: :none
135
+ )
136
+ ```
137
+
138
+ > Changed in 1.3.0: before 1.3.0 a datadir sent nothing even with a valid SDK
139
+ > key. See the CHANGELOG.
140
+
114
141
  ## Datadir mode: auto-reload on file changes
115
142
 
116
143
  In datadir mode the SDK loads the workspace once at construction time and then
@@ -140,10 +140,21 @@ module Quonfig
140
140
 
141
141
  # In datadir mode the SDK evaluates config from a local workspace and does
142
142
  # not connect to the delivery service.
143
+ #
144
+ # NOTE: this says nothing about telemetry. Datadir mode is a config-DELIVERY
145
+ # mode; usage telemetry still flows whenever an SDK key is configured. See
146
+ # #telemetry_allowed?.
143
147
  def local_only?
144
148
  !@datadir.nil?
145
149
  end
146
150
 
151
+ # True when an SDK key is configured. The SDK key is what identifies the
152
+ # workspace telemetry is attributed to, so it is the single gate on whether
153
+ # any collection happens at all (qfg-j001 / qfg-5x9x).
154
+ def sdk_key?
155
+ !(@sdk_key.nil? || @sdk_key.to_s.empty?)
156
+ end
157
+
147
158
  def datadir?
148
159
  !@datadir.nil?
149
160
  end
@@ -202,6 +213,13 @@ module Quonfig
202
213
  # Debounce window in milliseconds. Filesystem events arriving
203
214
  # inside the window are coalesced into a single re-read. Ignored
204
215
  # when +:data_dir_auto_reload+ is +false+.
216
+ # @option options [Boolean] :allow_telemetry_in_local_mode (false)
217
+ # @deprecated No-op since 1.3.0 (qfg-5x9x). Telemetry is gated on SDK-key
218
+ # presence alone, so datadir mode no longer suppresses it and this flag
219
+ # has nothing left to unlock. Still accepted so existing callers keep
220
+ # working; slated for removal in 2.0.0. To turn telemetry off, use the
221
+ # standard opt-outs (+:collect_evaluation_summaries+ +false+,
222
+ # +:context_upload_mode+ +:none+).
205
223
  def init(
206
224
  api_urls: nil,
207
225
  telemetry_url: nil,
@@ -226,6 +244,7 @@ module Quonfig
226
244
  context_max_size: DEFAULT_MAX_EVAL_SUMMARIES,
227
245
  collect_evaluation_summaries: true,
228
246
  collect_max_evaluation_summaries: DEFAULT_MAX_EVAL_SUMMARIES,
247
+ # Deprecated no-op since 1.3.0 (qfg-5x9x) — see the @option doc above.
229
248
  allow_telemetry_in_local_mode: false,
230
249
  global_context: {},
231
250
  logger_key: nil,
@@ -287,6 +306,7 @@ module Quonfig
287
306
  @collect_sync_interval = collect_sync_interval
288
307
  @collect_evaluation_summaries = collect_evaluation_summaries
289
308
  @collect_max_evaluation_summaries = collect_max_evaluation_summaries
309
+ # Retained for back-compat only; nothing reads it (qfg-5x9x).
290
310
  @allow_telemetry_in_local_mode = allow_telemetry_in_local_mode
291
311
  @is_fork = false
292
312
  @global_context = global_context
@@ -342,8 +362,21 @@ module Quonfig
342
362
  end
343
363
  end
344
364
 
365
+ # The telemetry gate: an explicit per-collector opt-out (+option+) AND the
366
+ # presence of an SDK key. Mode is deliberately NOT part of this decision.
367
+ #
368
+ # qfg-5x9x: this used to read
369
+ # `option && (!local_only? || @allow_telemetry_in_local_mode)`
370
+ # which zeroed every collect_max_* the moment a datadir was set, so a
371
+ # datadir client holding a perfectly valid SDK key built no aggregators and
372
+ # therefore never constructed a reporter — it emitted nothing at all.
373
+ # Datadir + SDK key is a supported combination and telemetry has to flow
374
+ # there like it does in delivery mode. Conversely a keyless client (the
375
+ # open-source / no-account path) has no workspace to attribute data to, so
376
+ # nothing is collected and the reporter never starts. Mirrors sdk-node's
377
+ # `isTelemetryEnabled` and sdk-go's `Options.TelemetryEnabled()`.
345
378
  def telemetry_allowed?(option)
346
- option && (!local_only? || @allow_telemetry_in_local_mode)
379
+ option && sdk_key?
347
380
  end
348
381
 
349
382
  def remove_trailing_slash(url)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quonfig
4
- VERSION = '1.2.0'
4
+ VERSION = '1.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quonfig
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.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-07-08 00:00:00.000000000 Z
11
+ date: 2026-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport