standard_health 0.7.1 → 0.8.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 +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +5 -1
- data/lib/standard_health/configuration.rb +25 -5
- data/lib/standard_health/env_spec.rb +19 -0
- data/lib/standard_health/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3cf58624de0179c4903a4159e227baa82079b2a78e97679122a429b186783918
|
|
4
|
+
data.tar.gz: 33963ed5e02ec9794a3133e4fbf3444cb443bc821045ec8bde6ecfb4b575f0a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 846b8334841aeb56c429f8a767f76c1e3e22e849da7f5de261370895cb3d7e735e2ee1fe3a72508637474f0338b34c05848bdda32e359bee783857ca3dd85e79
|
|
7
|
+
data.tar.gz: b6fefd789b745ec5a20819c46b89d610b226283b09024db1426ba5aacebee6838941f9d9c423b152bc55df2ab09bd341906cc5b15de6e2a7c0c59a5891d291f6
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.0] - 2026-10-22
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **Re-registering a check replaces it.** `register_check` and
|
|
15
|
+
`register_aggregate_check` replace an existing registration of the same name
|
|
16
|
+
in place (last writer wins) instead of appending a second one, matching
|
|
17
|
+
`register_diagnostics_assertion`. A `configure` block that runs twice, e.g.
|
|
18
|
+
from `to_prepare` on reload, no longer runs every check twice.
|
|
19
|
+
- **`env_spec` aliases are checked at boot.** Assigning `c.env_spec = …` calls
|
|
20
|
+
the new `EnvSpec#validate!`, which raises `EnvSpec::UnknownModeAlias` naming
|
|
21
|
+
every `in:` alias that has no `mode_alias`. Before, an undeclared alias raised
|
|
22
|
+
only on the first audit, which was a production `/diagnostics/env` request
|
|
23
|
+
(it 500'd one app's doctor tier once). All five estate apps declare every
|
|
24
|
+
alias they use, so none of them is affected.
|
|
25
|
+
|
|
10
26
|
## [0.7.1] - 2026-09-25
|
|
11
27
|
|
|
12
28
|
### Fixed
|
data/README.md
CHANGED
|
@@ -362,7 +362,7 @@ end
|
|
|
362
362
|
|
|
363
363
|
- `nil` (omitted) — entry always applies
|
|
364
364
|
- `Array<String>` — literal mode list (existing behaviour)
|
|
365
|
-
- `Symbol` — resolved against `mode_alias
|
|
365
|
+
- `Symbol` — resolved against `mode_alias`. Assigning the spec (`c.env_spec = …`) checks every alias, so an undeclared Symbol raises `StandardHealth::EnvSpec::UnknownModeAlias` at boot, naming each unknown alias, rather than on the first `/diagnostics/env` request.
|
|
366
366
|
|
|
367
367
|
### `description:` and `consumed_by:`
|
|
368
368
|
|
|
@@ -522,6 +522,10 @@ end
|
|
|
522
522
|
|
|
523
523
|
`with_timing` captures `latency_ms` on success and converts any `StandardError` into `{ status: :fail, error: <message> }`.
|
|
524
524
|
|
|
525
|
+
Registering a name that is already registered replaces that check in place (the
|
|
526
|
+
same for `register_aggregate_check`), so a `configure` block that runs twice,
|
|
527
|
+
e.g. from `to_prepare` on reload, doesn't run any check twice.
|
|
528
|
+
|
|
525
529
|
**Per-registration options (0.6.0).** Keywords other than `critical:` and
|
|
526
530
|
`timeout:` are forwarded to the check's constructor, and validated against its
|
|
527
531
|
signature at registration — a typo fails at boot, not on every probe:
|
|
@@ -86,7 +86,16 @@ module StandardHealth
|
|
|
86
86
|
# An optional `StandardHealth::EnvSpec` instance describing required and
|
|
87
87
|
# recommended environment variables for the host app. Audited via the
|
|
88
88
|
# /diagnostics/env endpoint.
|
|
89
|
-
|
|
89
|
+
attr_reader :env_spec
|
|
90
|
+
|
|
91
|
+
# Validates the spec as it is assigned (`EnvSpec#validate!`), so an
|
|
92
|
+
# `in:` alias with no `mode_alias` fails the initializer at boot rather
|
|
93
|
+
# than raising on the first audit, which is a /diagnostics/env request
|
|
94
|
+
# in production.
|
|
95
|
+
def env_spec=(spec)
|
|
96
|
+
spec.validate! if spec.respond_to?(:validate!)
|
|
97
|
+
@env_spec = spec
|
|
98
|
+
end
|
|
90
99
|
|
|
91
100
|
# --- Instrumentation -----------------------------------------------
|
|
92
101
|
#
|
|
@@ -270,13 +279,16 @@ module StandardHealth
|
|
|
270
279
|
# Validated against the constructor's signature HERE, so a typo fails
|
|
271
280
|
# at boot instead of turning into an ArgumentError on every probe (which
|
|
272
281
|
# the aggregator would dutifully report as a failing check forever).
|
|
282
|
+
#
|
|
283
|
+
# Re-registering a name replaces that registration in place (last writer
|
|
284
|
+
# wins), so `configure` can safely re-run, e.g. from `to_prepare` on
|
|
285
|
+
# reload, without running the check twice.
|
|
273
286
|
def register_check(name, klass, critical: false, timeout: nil, **options)
|
|
274
287
|
validate_check_options!(klass, options)
|
|
275
288
|
registration = Registration.new(
|
|
276
289
|
name: name.to_sym, klass: klass, critical: critical, timeout: timeout, options: options
|
|
277
290
|
)
|
|
278
|
-
@checks
|
|
279
|
-
registration
|
|
291
|
+
upsert_registration(@checks, registration)
|
|
280
292
|
end
|
|
281
293
|
|
|
282
294
|
# The check set every consumer app registers by hand. Each entry: default
|
|
@@ -362,13 +374,14 @@ module StandardHealth
|
|
|
362
374
|
#
|
|
363
375
|
# c.register_aggregate_check :solid_cable, StandardHealth::Checks::SolidCable
|
|
364
376
|
# c.register_aggregate_check :attestation_roots, "AttestationRootsCheck"
|
|
377
|
+
#
|
|
378
|
+
# Re-registering a name replaces it in place, as for #register_check.
|
|
365
379
|
def register_aggregate_check(name, klass, critical: false, timeout: nil, **options)
|
|
366
380
|
validate_check_options!(klass, options)
|
|
367
381
|
registration = Registration.new(
|
|
368
382
|
name: name.to_sym, klass: klass, critical: critical, timeout: timeout, options: options
|
|
369
383
|
)
|
|
370
|
-
@aggregate_checks
|
|
371
|
-
registration
|
|
384
|
+
upsert_registration(@aggregate_checks, registration)
|
|
372
385
|
end
|
|
373
386
|
|
|
374
387
|
DiagnosticsAssertion = Struct.new(:name, :callable)
|
|
@@ -440,6 +453,13 @@ module StandardHealth
|
|
|
440
453
|
|
|
441
454
|
private
|
|
442
455
|
|
|
456
|
+
# Replaces the registration with the same name in place, or appends.
|
|
457
|
+
def upsert_registration(registry, registration)
|
|
458
|
+
index = registry.index { |existing| existing.name == registration.name }
|
|
459
|
+
index ? registry[index] = registration : registry << registration
|
|
460
|
+
registration
|
|
461
|
+
end
|
|
462
|
+
|
|
443
463
|
# Rejects option keys the check's constructor cannot accept. Only
|
|
444
464
|
# inspects the signature — never instantiates — so a check with side
|
|
445
465
|
# effects in `initialize` is not run at boot. A constructor taking
|
|
@@ -115,6 +115,21 @@ module StandardHealth
|
|
|
115
115
|
@mode_aliases[name.to_sym] = Array(modes).map(&:to_s)
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
+
# Resolves every `in:` alias now. `Configuration#env_spec=` calls this,
|
|
119
|
+
# so an undeclared or misspelt alias fails at boot instead of raising on
|
|
120
|
+
# the first audit (a /diagnostics/env request, or an EnvSpecAudit row).
|
|
121
|
+
#
|
|
122
|
+
# @raise [UnknownModeAlias] naming every unknown alias
|
|
123
|
+
# @return [self]
|
|
124
|
+
def validate!
|
|
125
|
+
unknown = entries.filter_map { |entry| entry.modes if alias_unknown?(entry.modes) }.uniq
|
|
126
|
+
return self if unknown.empty?
|
|
127
|
+
|
|
128
|
+
raise UnknownModeAlias,
|
|
129
|
+
"Unknown mode alias#{"es" if unknown.size > 1}: #{unknown.map(&:inspect).join(", ")} " \
|
|
130
|
+
"(declare it with mode_alias)"
|
|
131
|
+
end
|
|
132
|
+
|
|
118
133
|
# Group subsequent declarations under a label. Pure metadata —
|
|
119
134
|
# propagated to audit rows as `group:` and otherwise inert. Nested
|
|
120
135
|
# `group` blocks are supported; the innermost label is the one that
|
|
@@ -253,6 +268,10 @@ module StandardHealth
|
|
|
253
268
|
modes.include?(mode_str)
|
|
254
269
|
end
|
|
255
270
|
|
|
271
|
+
def alias_unknown?(modes)
|
|
272
|
+
modes.is_a?(Symbol) && !@mode_aliases.key?(modes)
|
|
273
|
+
end
|
|
274
|
+
|
|
256
275
|
def resolve_modes(modes)
|
|
257
276
|
return nil if modes.nil?
|
|
258
277
|
if modes.is_a?(Symbol)
|