General
A deprecated value has to live somewhere, and widening the set was the wrong somewhere
Mahiro Hirakawa DEV Community
5 views
A check refused a row I had just added. The row was a retired signing key, kept so that records signed under it can still be read. The check said:
refused scheme_outside_the_set scheme=keyed_sha256 schemes=["ed25519"]
The set of accepted schemes has exactly one element, and a published limits document says so in one sentence. The retired key's scheme is not that element. The check was right.
Three places a deprecated value can go
option
what happens to old records
what happens to the published claim
widen the set to two
readable
now false
drop the old value
unreadable, permanently
stays true
a second, separate set
readable
stays true, scoped
The first is the one that costs nothing today. It also makes a sentence someone may have relied on quietly untrue, and there is no moment at which anyone is told.
The second is the one that feels principled and destroys history.
What went in was the third:
schemes = ["ed25519"] # may verify a new record
schemes_retired = ["keyed_sha256"] # may read an old one, never verify a new one
Two closed sets, with the boundary between them being a capability rather than a timestamp. A retired entry is not a weaker member of the live set. It is not a member of the live set at all.
What that actually cost
More than the two lines above, and the extras are the interesting part.
Two new refusal reasons, each with a control in both directions. It is not enough that a retired scheme is accepted for reading; a live scheme must still be refused where a retired one is expected, and vice versa. Two reasons, four controls.
The published claim was retired and re-stood, not edited. The old sentence said the set has one element. That was true and is still true of the live set. The document keeps the old sentence marked retired and adds the scoped one beside it, so a reader who saw the original can tell what happened to it.
OK_KEYS keys=1/1 declared=1/1 private_in_tree=0
keys_live=1 keys_retired=1 schemes_retired=1
The counts are printed separately on purpose. keys=1/1 alone would have been true and would have hidden the whole change.
The naming rule that stopped me making it worse
My first instinct for the two new reasons was to number them, following the sequence the surrounding codes use.
A rule in the same spec forbids that for this class of code. I was irritated by it for about a minute, and then noticed what numbering would have done: two other counters are computed over the numbered range, and adding two entries to that range would have made both of those counts wrong while every individual test stayed green.
The codes went in by property instead, in the section that carries codes of that kind. Nothing that counts the numbered range changed.
A naming convention that looks cosmetic was load-bearing because something downstream counted the names.
The consumer I did not update
One audit was left behind. It weighs every key row against the live set alone, so after the split it reads a false violation:
audit: scheme_outside_the_set=1 (the retired row, correctly recorded, wrongly judged)
That is not a new bug introduced by the split. It is the same defect that was always there, made visible by the split: that reader had no concept of a retired row, and until today no retired row existed for it to be wrong about.
It is recorded as a known gap with its own entry rather than patched in the same change. I would rather have one honest false positive with a name than a quiet edit that makes a reader agree without anyone checking why.
The rules
A closed set with no retired class forces a choice between a false claim and lost history. If a set can ever contain something deprecated, decide where deprecated things go before you need to put one there.
Splitting a set is an interface change for everything that reads it. Every consumer has an implicit assumption that the set means "all of them". Find those consumers, and where you cannot fix them today, record which ones you know are now wrong.
Check what counts your names before you add one. Numbering has a way of being a schema.
Read original: https://dev.to/mahirhir/a-deprecated-value-has-to-live-somewhere-and-widening-the-set-was-the-wrong-somewhere-4kh8
← Previous
Bot Detection False Positives: How to Actually Test Accuracy
Next →
ESLint took 4.4s to lint Vue's core. oxlint took 0.24s. Then I turned on the type-aware rules.
Related
My verifier accepted "13 of 13" by finding the number 13 once
General
0
Dev.to (EN Zone)
Show Me the Best Article You've Read And I'll Add It To My List
General
1
DEV Community
My registry accepted a duplicate ID, and the wrong thing failed three steps later
General
1
DEV Community
OpenResearch ให้ agent วิจัยหลายทิศทางพร้อมกัน โดยไม่ต้องส่งโค้ดออกไป
General
2
DEV Community 周榜
Comments0
No comments yet — be the first