hub: delete the host-install version label (R-94) + invert hostinstall gate 1
The Setup tab said 'host-install 1.19.0' while the served script was 1.22.0, and had been wrong since 2026-07-14. Deriving the number honestly is not possible: the Option-1 command downloads felhom-host-install.sh from the website at RUN TIME and the website git-syncs main every 30s (R-110), so no build-time value in the hub can be true. R-94(a) offered derive-or-delete; deleted, which removes the drift class instead of automating it. - configs.go: hostInstallVersion const, pageData.ScriptVersion field and its assignment all removed; a NOTE in their place records why there is no constant here. - customer_unified.html: the sentence now says the command always fetches the current installer, and renders no version. - hostinstall_gates.py gate 1: the third assertion INVERTS — it used to require the hub const to equal SCRIPT_VERSION, it now asserts the hub carries no host-install version literal at all, matched in six code shapes across every .go/.html under hub/ (comments are deliberately not stripped: a // inside a URL literal would blind the scan). - render_test.go: the assertion 'html contains hostInstallVersion' compared the constant to itself and passed at ANY value — demonstrated green with the const at 9.9.9 while the script was 1.22.0. Deleted, not replaced: there is no longer a version to assert. - felhom-host-install.sh: COMMENT ONLY (SCRIPT_VERSION untouched) — it claimed the gate keeps the hub copy equal, an invariant that no longer exists. Red-proofs: restoring the const fails the rewritten gate 1 (3 shapes hit); the old render_test assertion passes at 9.9.9.
This commit is contained in:
@@ -20,12 +20,14 @@ import (
|
|||||||
|
|
||||||
var validCustomerID = regexp.MustCompile(`^[a-zA-Z0-9.\-]+$`)
|
var validCustomerID = regexp.MustCompile(`^[a-zA-Z0-9.\-]+$`)
|
||||||
|
|
||||||
// hostInstallVersion is the felhom-host-install.sh version the customer page's install-command
|
// NOTE (R-94, 2026-08-02): there is deliberately NO host-install version constant here, and the
|
||||||
// generator targets. Kept in sync with scripts/felhom-host-install.sh SCRIPT_VERSION — the generator
|
// Setup tab renders no version number. The hub cannot know which version a box will run: the
|
||||||
// only ever emits flags this version parses. Display-only (the Option-1 command downloads the served
|
// Option-1 command downloads felhom-host-install.sh from the website at run time, and the website
|
||||||
// script, which is always current); bump when the generator's flag surface follows a new script.
|
// git-syncs `main` every 30s (R-110). Any build-time literal here is a guess wearing a version
|
||||||
// Drift is now gated: scripts/hostinstall_gates.py asserts this const == SCRIPT_VERSION (drill F-1).
|
// number's authority — the previous const said 1.19.0 while the served script was 1.22.0, and had
|
||||||
const hostInstallVersion = "1.19.0"
|
// been wrong since 2026-07-14. The single version source is scripts/felhom-host-install.sh's
|
||||||
|
// SCRIPT_VERSION; scripts/hostinstall_gates.py gate 1 now asserts this file's ABSENCE of any
|
||||||
|
// host-install version literal.
|
||||||
|
|
||||||
// validSemver matches a bare X.Y.Z controller version (the floor format). Empty is also accepted by
|
// validSemver matches a bare X.Y.Z controller version (the floor format). Empty is also accepted by
|
||||||
// the floor handlers (clears the override).
|
// the floor handlers (clears the override).
|
||||||
@@ -331,9 +333,6 @@ func (s *Server) handleCustomerUnified(w http.ResponseWriter, r *http.Request, c
|
|||||||
CSRFField template.HTML
|
CSRFField template.HTML
|
||||||
CSRFToken string
|
CSRFToken string
|
||||||
|
|
||||||
// ScriptVersion drives the install-command generator's header (GL-7). Display-only.
|
|
||||||
ScriptVersion string
|
|
||||||
|
|
||||||
// Hosts (v0.47.0): the customer's enrolled hosts for the Host tab — a LIST by design
|
// Hosts (v0.47.0): the customer's enrolled hosts for the Host tab — a LIST by design
|
||||||
// (1 today, N for a later HA cluster). Each entry is the hostDetailData view-model map
|
// (1 today, N for a later HA cluster). Each entry is the hostDetailData view-model map
|
||||||
// the shared host_detail_body sub-template renders.
|
// the shared host_detail_body sub-template renders.
|
||||||
@@ -484,8 +483,6 @@ func (s *Server) handleCustomerUnified(w http.ResponseWriter, r *http.Request, c
|
|||||||
CSRFField: s.csrfField(r),
|
CSRFField: s.csrfField(r),
|
||||||
CSRFToken: s.csrfToken(r),
|
CSRFToken: s.csrfToken(r),
|
||||||
|
|
||||||
ScriptVersion: hostInstallVersion,
|
|
||||||
|
|
||||||
Hosts: hostViews,
|
Hosts: hostViews,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -215,10 +215,11 @@ func TestTemplates_InstallGenerator(t *testing.T) {
|
|||||||
t.Errorf("generator control missing: %s", id)
|
t.Errorf("generator control missing: %s", id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// targets the right script version + carries the client-side customer id
|
// carries the client-side customer id. There is deliberately NO version assertion here: R-94
|
||||||
if !strings.Contains(html, hostInstallVersion) {
|
// deleted the rendered host-install version, because the hub cannot know which version a box
|
||||||
t.Errorf("ScriptVersion %s not rendered", hostInstallVersion)
|
// will run (the script is fetched at run time). The assertion that used to sit here compared
|
||||||
}
|
// hostInstallVersion to itself and passed at any value — it was demonstrated green with the
|
||||||
|
// const set to "9.9.9" while the served script was 1.22.0.
|
||||||
if !strings.Contains(html, `data-customer-id="peti-felhom"`) {
|
if !strings.Contains(html, `data-customer-id="peti-felhom"`) {
|
||||||
t.Errorf("generator missing data-customer-id")
|
t.Errorf("generator missing data-customer-id")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -491,9 +491,10 @@
|
|||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Setup Command</h2>
|
<h2>Setup Command</h2>
|
||||||
<p class="text-muted" style="margin-bottom: 1rem; font-size: 0.85rem;">
|
<p class="text-muted" style="margin-bottom: 1rem; font-size: 0.85rem;">
|
||||||
Day-0 host bootstrap for host-install <strong>{{.ScriptVersion}}</strong>. Run on a
|
Day-0 host bootstrap. The command always fetches the <strong>current</strong>
|
||||||
freshly-PVE-installed Proxmox <strong>host</strong> as root (create the customer in the
|
felhom-host-install.sh from felhom.eu — there is no version to pick here. Run it
|
||||||
hub first). It enrolls the host, installs + verifies the agent, and provisions the guest;
|
on a freshly-PVE-installed Proxmox <strong>host</strong> as root (create the customer in
|
||||||
|
the hub first). It enrolls the host, installs + verifies the agent, and provisions the guest;
|
||||||
the in-guest controller then pulls its own <code>controller.yaml</code>. The retrieval
|
the in-guest controller then pulls its own <code>controller.yaml</code>. The retrieval
|
||||||
passphrase is entered at the no-echo prompt — never on the command line.
|
passphrase is entered at the no-echo prompt — never on the command line.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -184,9 +184,11 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_VERSION="1.22.0" # the SINGLE version source (F-1): -h, the run banners, and the hub
|
SCRIPT_VERSION="1.22.0" # the SINGLE version source (F-1): -h and the run banners follow it.
|
||||||
# Setup-tab copy (hub internal/web/configs.go hostInstallVersion —
|
# The hub used to carry a copy for its Setup tab; R-94 DELETED it
|
||||||
# scripts/hostinstall_gates.py asserts the two stay equal) all follow it.
|
# (2026-08-02) because the hub cannot know which version a box runs —
|
||||||
|
# the Setup command fetches this script at run time. scripts/
|
||||||
|
# hostinstall_gates.py now asserts the hub carries NO version literal.
|
||||||
# 1.16.0: the FELHOM_ESCROW sudoers alias (controller-driven escrow
|
# 1.16.0: the FELHOM_ESCROW sudoers alias (controller-driven escrow
|
||||||
# ceremony, agent v0.88.0) ships on every install/update — it rides the
|
# ceremony, agent v0.88.0) ships on every install/update — it rides the
|
||||||
# CANONICAL sudoers fetch below (configs/felhom-agent.sudoers from the
|
# CANONICAL sudoers fetch below (configs/felhom-agent.sudoers from the
|
||||||
|
|||||||
@@ -5,9 +5,17 @@ drill-swept findings (DRILL-day0-vm-2026-07-12 F-1/F-7/F-9/F-10 + the ACL-narrow
|
|||||||
Run from the repo root: python scripts/hostinstall_gates.py
|
Run from the repo root: python scripts/hostinstall_gates.py
|
||||||
|
|
||||||
Gates (all must pass; non-zero exit on any failure):
|
Gates (all must pass; non-zero exit on any failure):
|
||||||
1. version — exactly ONE version source: SCRIPT_VERSION exists, the header line carries
|
1. version — exactly ONE version source: SCRIPT_VERSION exists, the header line carries no
|
||||||
no version literal, and the hub Setup-tab const (hub internal/web/configs.go
|
version literal, and **the hub carries no host-install version literal at all**.
|
||||||
hostInstallVersion) equals SCRIPT_VERSION (F-1 structural fix)
|
The third assertion inverted on 2026-08-02 (R-94): it used to require the hub's
|
||||||
|
`hostInstallVersion` const to EQUAL SCRIPT_VERSION, which is unachievable
|
||||||
|
honestly — the Option-1 install command downloads felhom-host-install.sh from
|
||||||
|
the website at RUN TIME and the website git-syncs `main` every 30 seconds
|
||||||
|
(R-110), so the hub cannot know which version a given box will run. A
|
||||||
|
build-time literal there is a guess with a version number's authority, and the
|
||||||
|
real one drifted to 1.19.0-vs-1.22.0 and stayed wrong for 19 days. The label was
|
||||||
|
deleted rather than derived; this gate now pins its absence (F-1 structural fix,
|
||||||
|
second form).
|
||||||
2. age — the `age` package is installed by the agent-install step (F-10)
|
2. age — the `age` package is installed by the agent-install step (F-10)
|
||||||
3. pbs-apply — configs/felhom-pbs-apply is fetched + installed to
|
3. pbs-apply — configs/felhom-pbs-apply is fetched + installed to
|
||||||
/usr/local/sbin/felhom-pbs-apply (F-7), and the uninstall removes it
|
/usr/local/sbin/felhom-pbs-apply (F-7), and the uninstall removes it
|
||||||
@@ -54,21 +62,49 @@ if re.search(r'felhom-host-install\.sh\s+v\d+\.\d+\.\d+', header):
|
|||||||
else:
|
else:
|
||||||
ok("header has no version literal")
|
ok("header has no version literal")
|
||||||
|
|
||||||
# hub Setup-tab const must equal SCRIPT_VERSION (the copy the drill found at 1.12.0).
|
# The hub must carry NO host-install version literal at all (R-94, 2026-08-02). It cannot know
|
||||||
if os.path.exists(HUB_CONFIGS) and script_ver:
|
# which version a box will run — the Option-1 command fetches the script from the website at run
|
||||||
with io.open(HUB_CONFIGS, "r", encoding="utf-8") as f:
|
# time and the website git-syncs `main` every 30s. The const this replaced said 1.19.0 while the
|
||||||
hub_src = f.read()
|
# served script was 1.22.0, and had been wrong since 2026-07-14.
|
||||||
hm = re.search(r'hostInstallVersion\s*=\s*"(\d+\.\d+\.\d+)"', hub_src)
|
#
|
||||||
if not hm:
|
# Matched in CODE SHAPES, never as bare prose: the deleted declarations, the struct field, the
|
||||||
fail("hub hostInstallVersion const not found in internal/web/configs.go")
|
# assignment and the template action, plus a rename-proof generic form of each. Comments are
|
||||||
elif hm.group(1) != script_ver:
|
# deliberately NOT stripped (a `//` inside a URL string literal would truncate the scan and turn
|
||||||
fail("hub Setup-tab hostInstallVersion=%s != SCRIPT_VERSION=%s (F-1: bump both together)"
|
# this gate blind); a comment that merely NAMES the identifier is allowed, and configs.go carries
|
||||||
% (hm.group(1), script_ver))
|
# exactly such a note explaining the absence.
|
||||||
else:
|
BANNED = [
|
||||||
ok("hub Setup-tab hostInstallVersion matches (%s)" % hm.group(1))
|
(r'\bconst\s+hostInstallVersion\b', "const hostInstallVersion"),
|
||||||
|
(r'\bhostInstallVersion\s*=', "hostInstallVersion assignment"),
|
||||||
|
(r'(?i)\bconst\s+\w*hostinstall\w*version\b', "a renamed host-install version const"),
|
||||||
|
(r'\bScriptVersion\s+string\b', "ScriptVersion struct field"),
|
||||||
|
(r'\bScriptVersion\s*:', "ScriptVersion struct assignment"),
|
||||||
|
(r'\{\{\s*\.ScriptVersion\s*\}\}', "{{.ScriptVersion}} template action"),
|
||||||
|
]
|
||||||
|
HUB_DIR = os.path.join(ROOT, "hub")
|
||||||
|
if not os.path.isdir(HUB_DIR):
|
||||||
|
fail("hub/ not found at %s — cannot assert the absence of a host-install version literal" % HUB_DIR)
|
||||||
else:
|
else:
|
||||||
if not os.path.exists(HUB_CONFIGS):
|
scanned, hits = 0, 0
|
||||||
fail("hub/internal/web/configs.go not found — cannot cross-check the Setup-tab version")
|
for dirpath, dirs, files in os.walk(HUB_DIR):
|
||||||
|
dirs[:] = [d for d in dirs if d not in (".git", "vendor", "node_modules")]
|
||||||
|
for fn in files:
|
||||||
|
if not (fn.endswith(".go") or fn.endswith(".html")):
|
||||||
|
continue
|
||||||
|
fp = os.path.join(dirpath, fn)
|
||||||
|
scanned += 1
|
||||||
|
with io.open(fp, "r", encoding="utf-8") as f:
|
||||||
|
for lineno, line in enumerate(f, 1):
|
||||||
|
for pat, what in BANNED:
|
||||||
|
if re.search(pat, line):
|
||||||
|
hits += 1
|
||||||
|
fail("%s:%d carries %s — the hub must render NO host-install version "
|
||||||
|
"(R-94: the served script is fetched at run time, so no build-time "
|
||||||
|
"value can be true). Single source: scripts/felhom-host-install.sh "
|
||||||
|
"SCRIPT_VERSION. Line: %s"
|
||||||
|
% (os.path.relpath(fp, ROOT), lineno, what, line.strip()[:120]))
|
||||||
|
if not hits:
|
||||||
|
ok("hub carries no host-install version literal (%d .go/.html files scanned, %d shapes checked)"
|
||||||
|
% (scanned, len(BANNED)))
|
||||||
|
|
||||||
# ── 2. age package (F-10) ───────────────────────────────────────────────────────
|
# ── 2. age package (F-10) ───────────────────────────────────────────────────────
|
||||||
# must match the REAL install invocation, not the log_dry echo (red-proof-hardened twice:
|
# must match the REAL install invocation, not the log_dry echo (red-proof-hardened twice:
|
||||||
|
|||||||
Reference in New Issue
Block a user