Files
felhom-controller/controller/internal/web/r1219_no_ceremony_during_offer_test.go
T
admin 1170b48e59 fix(R-1218, R-1219): stage the off-site password when its file exists; no recovery ceremony during a recovery offer
R-1218: escrowStart stages when OffboxRepoPasswordOnBox() (not OffboxConfigured()). R-1219: the top bar hides during an
offer; the start handler answers 409 (api.escrow.recovery_offer_open, hu+en) before staging. Red-proved. Commit only.
2026-10-26 20:20:59 +01:00

70 lines
2.9 KiB
Go

package web
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
)
// offerShapeC puts the harness box in the recovery offer, shape (c): the hub holds a package for a DIFFERENT repository
// key than the one the box uses — the old off-site copy opens only with the household's EXISTING recovery code.
func offerShapeC(t *testing.T, h *escrowWizardHarness) {
t.Helper()
h.configureOffbox(t, "pending")
if err := h.sett.SetHubEscrowIdentityPresent(true); err != nil {
t.Fatal(err)
}
if err := h.sett.SetHubEscrowKeySHA256("0000000000000000000000000000000000000000000000000000000000000000", "2026-10-26T20:00:00Z"); err != nil {
t.Fatal(err)
}
if !h.m.OffsiteRecoveryOffer() {
t.Fatal("setup: the box should be in the recovery offer")
}
}
// R-1219: during a recovery offer a NEW recovery code would replace the key that opens the old off-site copy (R-199).
// The backups page already hid the ceremony; the global top bar still linked to it and the start handler ran it. Now
// the bar is not shown and the start handler answers 409 with a sentence in the household's language, BEFORE anything
// is staged or started. COMPANION RED-PROOF: before the fix the bar was visible and the start answered 200
// („preflight,stage,start").
func TestR1219_NoCeremonyDuringARecoveryOffer(t *testing.T) {
h := newEscrowWizardHarness(t)
offerShapeC(t, h)
if !h.s.escrowPaused() {
t.Fatal("setup: the tier should read as paused (pending) — the bar would otherwise be hidden for another reason")
}
r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{Name: sessionCookieName, Value: newTestSession(h.s)})
if h.s.escrowBannerVisible(r) {
t.Error("the top bar urges the recovery-code ceremony during a recovery offer")
}
w := postStart(t, h.s, wizardPassword)
if w.Code != http.StatusConflict {
t.Fatalf("start during an offer = %d (%s), want 409", w.Code, w.Body.String())
}
if !strings.Contains(w.Body.String(), "helyre") { // ASCII fragment of the Hungarian sentence (ui-hungarian rule)
t.Errorf("the refusal does not say why in Hungarian: %s", w.Body.String())
}
for _, step := range h.order {
if step == "stage" || step == "start" {
t.Fatalf("the agent was reached during an offer: %v", h.order)
}
}
}
// The control for the bar half: the SAME paused box with no recovery offer, the same logged-in request — the bar IS
// shown. Without this, a bar hidden for any other reason (no session, readiness) would pass the test above.
func TestR1219_TheBarStillShowsWithoutAnOffer(t *testing.T) {
h := newEscrowWizardHarness(t)
h.configureOffbox(t, "pending")
if h.m.OffsiteRecoveryOffer() {
t.Fatal("setup: no offer expected")
}
r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{Name: sessionCookieName, Value: newTestSession(h.s)})
if !h.s.escrowBannerVisible(r) {
t.Fatal("the bar is hidden on a paused box with no offer — the offer test above would prove nothing")
}
}