Files
felhom.eu/hub/internal/web/passphrase_handover_test.go
T
admin 6fd8c87516
gates / gates (push) Successful in 19s
doorstep: console is Felhom's (ISO 1.27.0 source), passphrase hand-over copy (hub 0.113.0 source), rulings
Phase 0: the public ISO never auto-installs by construction (no answer.toml,
G1); the operator re-affirmed the interactive installer 2026-09-14.
- felhom-bootstrap.sh: mask pvebanner.service, write a Hungarian /etc/issue
  (no :8006 admin URL); pairing banner names the Tulajdonosi jelmondat and
  paints through the CONSOLE_DEV seam (R-496). Harness: 8 checks, red first;
  fake hub now sends a pairing code (the banner was never tested, R-502).
- hub: created flash + Credentials block tell the operator to hand the phrase
  over; the self-bind mail names the operator (R-497). Tests red first.
- iso-release-gate G14-G16; domain ruling in 01-topology + CONTEXT; R-494
  narrowed to P3; R-502..R-504 filed; volunteer guide and day-0 A.2 aligned.
ISO_VERSION 1.27.0 (not built, not published).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-14 17:26:53 +02:00

69 lines
3.1 KiB
Go

package web
// R-497 — the „Tulajdonosi jelmondat" is delivered by NOTHING in the product: it is minted at customer
// creation, shown only on the operator's customer page, and never e-mailed (the operator has not ruled
// that e-mail may carry it). Measured 2026-09-14 in the first-hour drill: the self-bind mail told the
// customer they had received it „a beállításkor" — true only if the operator remembered to hand it over,
// and nothing told the operator to.
//
// These pin the CONSEQUENCE, not a string for its own sake: the operator is told at the moment the
// phrase exists, the page repeats it where the phrase is shown, and the customer's mail names the person
// they got it from. The last test pins what must NOT change — the mail still carries no phrase.
import (
"strings"
"testing"
"gitea.dooplex.hu/admin/felhom-hub/internal/notify"
)
// handoverMarker is the operator-facing instruction. One sentence, rendered in two places.
const handoverMarker = "Hand this phrase to the customer now"
func TestCustomerPage_CreatedFlashTellsTheOperatorToHandOverThePhrase(t *testing.T) {
s, st := newTestServer(t)
seedCustomer(t, st, "acme", "")
created := renderCustomerPageWithQuery(t, s, "acme", "?flash=created")
if !strings.Contains(created, handoverMarker) {
t.Errorf("the customer-created flash does not tell the operator to hand over the phrase:\n%s", created)
}
if !strings.Contains(created, "never e-mailed") {
t.Error("the created flash must say the phrase is never e-mailed — otherwise the operator waits for a mail")
}
// Nominal page (no flash): the instruction stays beside the phrase, where the operator reveals it.
plain := renderCustomerPage(t, s, "acme")
if !strings.Contains(plain, handoverMarker) {
t.Error("the Credentials block does not repeat the hand-over sentence beside the phrase")
}
}
func TestSelfBindEmail_SaysWhoHandedOverThePhrase(t *testing.T) {
_, body := notify.FormatSelfBindEmail("acme", "https://hub.example/bind/tok")
if strings.Contains(body, "beállításkor kaptál") {
t.Error("the mail still says the customer received the phrase „a beállításkor” — nothing delivers it then")
}
if !strings.Contains(body, "üzemeltetőjétől") {
t.Errorf("the mail must name who hands over the phrase (the Felhom operator):\n%s", body)
}
// Unchanged contract: one name, and what the thing is.
if !strings.Contains(body, "tulajdonosi jelmondatodat") || !strings.Contains(body, "5 szóból álló kifejezést") {
t.Error("the mail lost the secret's name or its description")
}
}
// The phrase itself must never ride the mail. A customer with a seeded phrase gets a mail that does not
// contain it — the builder takes no phrase argument today; this pins that no future edit adds one via
// the link text or a helper.
func TestSelfBindEmail_NeverCarriesThePhrase(t *testing.T) {
const phrase = "alma korte szilva barack meggy"
_, body := notify.FormatSelfBindEmail("acme", "https://hub.example/bind/tok")
for _, w := range strings.Fields(phrase) {
if strings.Contains(body, w) {
t.Errorf("the self-bind mail contains a passphrase word %q", w)
}
}
}