5270bad76e
gates / gates (push) Successful in 23s
Slice 1 translated the dashboard's markup. The sentences the program BUILDS were still Hungarian literals in Go, so an English household clicked an English button and was answered in Hungarian. 226 of them move into the bundle here. A flash was the hard part: it travels inside the redirect URL and is rendered by a DIFFERENT request, so it now carries a bundle key plus its parameters. A link minted by an older controller carries prose and is shown verbatim — never a raw key, never dropped. Also converted: page data and view-model text, the internal/api JSON answers, the alert banners (Alert.MessageKey, rendered on the way out of GetAlerts), 237 country names at display, and the four page titles built around an app name (R-566 closed). Hungarian is byte-identical, and that is measured rather than read: scripts/i18n_go_parity.py freezes every Go literal at the base commit (7 467) and refuses a key whose Hungarian is not that text, byte for byte. Three decoys, each seen to convict. Its own first version filtered the capture through an ASCII-Hungarian word list and missed seven real literals — the R-565 class. The filter is gone. Nothing on the wire moved, and wire goldens now hold it there: the report's health warnings and every notify event message stay Hungarian, because the hub MAILS the controller's sentence when it has no entry of its own. Slice 3 (R-558) owns those. MinAgent: 0.131.0 (unchanged). No hub release needed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
73 lines
3.0 KiB
Go
73 lines
3.0 KiB
Go
package api
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/system"
|
|
)
|
|
|
|
func newDeployGateRouter(t *testing.T, class string) *Router {
|
|
t.Helper()
|
|
lg := log.New(io.Discard, "", 0)
|
|
sett, err := settings.Load(filepath.Join(t.TempDir(), "settings.json"), lg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := sett.AddStoragePath(settings.StoragePath{
|
|
Path: "/mnt/felhom-drives/nas-media", Label: "NAS", Schedulable: true, Kind: settings.StorageKindNetwork,
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := sett.AddStoragePath(settings.StoragePath{
|
|
Path: "/mnt/felhom-drives/felhom-usb", Label: "USB", Schedulable: true,
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r := &Router{sett: sett, logger: lg}
|
|
r.classifyFSPath = func(string) string { return class }
|
|
return r
|
|
}
|
|
|
|
// The deploy-time stub gate (RCA fix 2): a registered network HDD_PATH that classifies as a STUB
|
|
// in this namespace refuses with the §2.3 Hungarian message; the healthy idle autofs trigger, a
|
|
// live mount, an unknown verdict (fail open), local paths and empty paths all proceed.
|
|
// Companion red-proofs:
|
|
// - remove the gate call from deployStack → the refusal test fails (deploy proceeds onto a stub);
|
|
// - an impl requiring MOUNTED-only (refusing autofs) → the idle-autofs row fails (it would
|
|
// wrongly block deploying onto a healthy idle share).
|
|
func TestRefuseNetworkStubDeploy_Table(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
class string
|
|
hdd string
|
|
refuse bool
|
|
}{
|
|
{"stub on network path → REFUSE", system.FSClassStub, "/mnt/felhom-drives/nas-media", true},
|
|
{"idle autofs on network path → proceed (healthy)", system.FSClassAutofs, "/mnt/felhom-drives/nas-media", false},
|
|
{"live network fs → proceed", system.FSClassNetwork, "/mnt/felhom-drives/nas-media", false},
|
|
{"unknown (timeout) → proceed (fail open)", system.FSClassUnknown, "/mnt/felhom-drives/nas-media", false},
|
|
{"local path → proceed even when classifier says stub", system.FSClassStub, "/mnt/felhom-drives/felhom-usb", false},
|
|
{"unregistered path → proceed", system.FSClassStub, "/mnt/elsewhere", false},
|
|
{"empty HDD_PATH (SSD app) → proceed", system.FSClassStub, "", false},
|
|
}
|
|
for _, c := range cases {
|
|
r := newDeployGateRouter(t, c.class)
|
|
// v0.252.0 (R-557): the gate returns a bundle KEY, so the customer reads it in their own
|
|
// language. Rendered here rather than compared as a key, because what this test is about is
|
|
// the SENTENCE the customer is refused with -- a key renamed with its message intact is not
|
|
// a regression, and a message reworded is.
|
|
msg := r.msgLang("hu", r.refuseNetworkStubDeploy(c.hdd))
|
|
if c.refuse && !strings.Contains(msg, "a telepítés nem indítható") {
|
|
t.Errorf("%s: want the refusal message, got %q", c.name, msg)
|
|
}
|
|
if !c.refuse && r.refuseNetworkStubDeploy(c.hdd) != "" {
|
|
t.Errorf("%s: must proceed, got refusal %q", c.name, msg)
|
|
}
|
|
}
|
|
}
|