v0.308.0 (R-554, held-back-able): recovery-info.txt points at the dashboard's Restore page and the recovery code; the first-boot setup wizard is deleted

Operator ruling 2026-10-12 (S27, 09 §3 decision 222). The operator approves the Hungarian text before
release. A box whose first ingestion failed now serves one bilingual waiting page and retries every
minute instead of the wizard. Own commit so the lead can hold it back.

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-12 15:38:28 +02:00
parent fd28d70bff
commit faef8f8a91
36 changed files with 421 additions and 1916 deletions
+40 -31
View File
@@ -4,55 +4,64 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
"gitea.dooplex.hu/admin/felhom-controller/internal/i18n"
)
// Info holds the data needed for the recovery info file and settings UI.
// Info holds the data needed for the recovery info file.
type Info struct {
CustomerID string
RetrievalPassword string
HubURL string
SupportEmail string
SupportURL string
// DashboardURL is the household's dashboard, e.g. https://felhom.<domain> (R-554, v0.308.0): the file
// points at its Restore page and its „Adatok visszaszerzése" page, not at the deleted setup wizard.
DashboardURL string
// Lang is the box's language; the file is written in it (Hungarian when empty or unknown).
Lang string
}
// GenerateRecoveryFile writes a plain text recovery-info.txt to the given directory.
func GenerateRecoveryFile(info Info, version, outputDir string) error {
if err := os.MkdirAll(outputDir, 0755); err != nil {
return fmt.Errorf("creating recovery info directory: %w", err)
// recoveryInfoKey is the file's text in the bundle (hu.json / en.json), with ten %s, in order:
// customer id, hub URL, retrieval password, support e-mail, support web, dashboard, restore page,
// recovery page, generated-at, controller version.
const recoveryInfoKey = "recovery_info.body"
// Render returns the text of recovery-info.txt (R-554, `09` §3 decision 222): what to do when something must
// be restored — the dashboard's Backup → Restore page, and after a reinstall the recovery code on the
// „Adatok visszaszerzése" page. Pinned by TestRecoveryInfo_PointsAtDashboardNotWizard.
func Render(info Info, version string, now time.Time) (string, error) {
b, err := i18n.Shared()
if err != nil {
return "", fmt.Errorf("loading message bundle: %w", err)
}
content := fmt.Sprintf(`Felhom Controller — Vészhelyzeti információk
=============================================
Ügyfél azonosító: %s
Hub URL: %s
Visszaállítási jelszó: %s
Támogatás:
Email: %s
Web: %s
Visszaállítási útmutató:
1. Telepítse az operációs rendszert (Debian 13)
2. Futtassa a docker-setup.sh szkriptet:
sudo ./docker-setup.sh --domain <domain>
3. Nyissa meg a böngészőben: http://<ip>:8081
4. Válassza a "Visszaállítás mentésből" opciót
5. Adja meg az ügyfél azonosítót és a visszaállítási jelszót
6. Kövesse a varázsló utasításait
Generálva: %s
Controller verzió: %s
`,
dash := strings.TrimRight(info.DashboardURL, "/")
return b.Msgf(i18n.Normalize(info.Lang), recoveryInfoKey,
info.CustomerID,
info.HubURL,
info.RetrievalPassword,
info.SupportEmail,
info.SupportURL,
time.Now().Format("2006-01-02 15:04:05"),
dash,
dash+"/backups/restore",
dash+"/recovery",
now.Format("2006-01-02 15:04:05"),
version,
)
), nil
}
// GenerateRecoveryFile writes a plain text recovery-info.txt to the given directory (0600: it holds the
// retrieval password).
func GenerateRecoveryFile(info Info, version, outputDir string) error {
if err := os.MkdirAll(outputDir, 0755); err != nil {
return fmt.Errorf("creating recovery info directory: %w", err)
}
content, err := Render(info, version, time.Now())
if err != nil {
return err
}
path := filepath.Join(outputDir, "recovery-info.txt")
tmp := path + ".tmp"