R-304: the recovery screen says 'we do not know' when earlier packages were not checked (hu + en)
gates / gates (push) Successful in 54s

Unreleased; ships with tomorrow's release.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-08 07:53:09 +02:00
parent 6d07ca2be4
commit 75b3b39254
7 changed files with 94 additions and 1 deletions
+12
View File
@@ -210,6 +210,10 @@ const (
// out loud — a true sentence about our own incuriosity that a customer reads as a statement about
// their code.
RecoveryCodeOpensRetained
// RecoveryOlderUnchecked — the code did not open the current package, no earlier package opened it, and
// NOT every earlier package the hub holds was tried (R-304, agent 424). So whether the code is wrong is
// NOT known. The customer must not be told to check their typing as if it were.
RecoveryOlderUnchecked
)
// ClassifyRecoveryFailure maps an unlock error to its class, from the VALUE and never the text.
@@ -251,6 +255,12 @@ func ClassifyRecoveryFailure(err error, trustRefusal, trustRetained bool) Recove
return RecoveryCodeOpensRetained
}
return RecoveryUnknown
case http.StatusFailedDependency:
// R-304. NOT version-gated, deliberately — unlike 400 and 422 above. Those two make a claim about the
// customer's code (wrong / correct), so a status we did not design must not be read as one. This class
// claims only „not everything was checked; contact support", which is the same direction as
// RecoveryUnknown: misreading a stray 424 here can never accuse anyone.
return RecoveryOlderUnchecked
case http.StatusBadRequest:
if trustRefusal {
return RecoveryAskedAndRefused
@@ -276,6 +286,8 @@ func (f RecoveryFailure) String() string {
return "bundle-too-old"
case RecoveryCodeOpensRetained:
return "code-opens-retained"
case RecoveryOlderUnchecked:
return "older-unchecked"
default:
return "unknown"
}