R-970: the box's hub key opens no route; Data tab leftovers; R-1103: the install form's dead branches
gates / gates (push) Successful in 48s

R-970: /api/config, /api/config/hash, /api/config/apply removed (they read and replaced controller.yaml with
every secret, reachable with the box's own hub API key, unsigned; nothing called them). The hub-key Bearer
door on /api/selfupdate/ and /api/geo/ and the matching CSRF exemption are gone; the dashboard keeps using
those with a session. The route table is buildMux, so a test drives the real one.

Data tab: the export password field is autocomplete=new-password with a non-login name; the 2nd copy's
status rows that repeated the form are gone (the no-target reason moves into the form).

R-1103: app_fields.html loses its installed-only branches (no page serves them since R-1095); the tests
that rendered that dead path are retired, their rules asserted on the settings tab (R-694 moved there).

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-16 18:24:00 +02:00
parent 8fe46a1313
commit f037be7a6a
25 changed files with 331 additions and 2987 deletions
@@ -299,18 +299,6 @@ function appMigrate(btn,app,label){
<div class="app-field-label">Éjszakai mentés</div>
<div class="app-field-value">Az alkalmazás adatbázisa és belső tárolói minden éjjel bekerülnek a mentésbe. <a href="/backups" class="app-info-link">Mentési állapot →</a></div>
</div>
<div class="app-field-row" data-backup-row="second">
<div class="app-field-label">2. mentés</div>
<div class="app-field-value">Bekapcsolva</div>
</div>
<div class="app-field-row" data-backup-row="target">
<div class="app-field-label">Cél meghajtó</div>
<div class="app-field-value">HDD kettő</div>
</div>
<div class="app-field-row">
<div class="app-field-label">Kiválasztás módja</div>
<div class="app-field-value">automatikus — a legnagyobb szabad hely</div>
</div>
<p class="app-field-hint" style="margin-top:12px">A 2. mentés egy <strong>másik meghajtóra</strong> másolja az alkalmazás helyreállítási csomagját és adatait. A böngészhető fájljaidat csak ez védi meg egy meghajtóhiba ellen — a teljes rendszermentés ezeket nem tartalmazza.</p>
@@ -331,6 +319,7 @@ function appMigrate(btn,app,label){
</select>
<div style="font-size:.8rem;color:var(--text-3);margin-top:.4rem">
Nincs másik adatmeghajtó — automatikusan a belső SSD-re kerül (csak az adatbázis és a beállítások). Egy 2. adatmeghajtóval a teljes adat is másik meghajtóra menthető.
</div>
@@ -392,7 +381,8 @@ function appMigrate(btn,app,label){
<h3>Jelszó (opcionális)</h3>
<div style="display:flex;gap:.5rem;margin-bottom:1rem">
<input type="password" id="exportPassword" class="form-control" placeholder="Titkosítási jelszó" style="flex:1">
<input type="password" id="fabEncryptionKey" name="fab_encryption_key" autocomplete="new-password" data-export-key="1" class="form-control" placeholder="Titkosítási jelszó" style="flex:1">
<button class="btn btn-sm btn-outline" onclick="togglePw(this)" type="button" id="exportPwToggle" aria-label="Jelszó mutatása">Megjelenítés</button>
</div>
@@ -435,7 +425,7 @@ function csrfH() {
}
function togglePw(btn) {
var inp = document.getElementById('exportPassword');
var inp = document.getElementById('fabEncryptionKey');
var show = inp.type === 'password';
inp.type = show ? 'text' : 'password';
if (btn) { btn.textContent = show ? 'Elrejtés' : 'Megjelenítés'; }
@@ -557,7 +547,7 @@ function esc(s) { return String(s).replace(/[&<>"]/g, function(c){ return {'&':'
async function startExport() {
var drive = document.getElementById('destDrive').value;
var password = document.getElementById('exportPassword').value;
var password = document.getElementById('fabEncryptionKey').value;
var stopApp = document.getElementById('stopApp').checked;
document.getElementById('startBtn').disabled = true;
@@ -287,7 +287,8 @@
<h3>Jelszó (opcionális)</h3>
<div style="display:flex;gap:.5rem;margin-bottom:1rem">
<input type="password" id="exportPassword" class="form-control" placeholder="Titkosítási jelszó" style="flex:1">
<input type="password" id="fabEncryptionKey" name="fab_encryption_key" autocomplete="new-password" data-export-key="1" class="form-control" placeholder="Titkosítási jelszó" style="flex:1">
<button class="btn btn-sm btn-outline" onclick="togglePw(this)" type="button" id="exportPwToggle" aria-label="Jelszó mutatása">Megjelenítés</button>
</div>
@@ -330,7 +331,7 @@ function csrfH() {
}
function togglePw(btn) {
var inp = document.getElementById('exportPassword');
var inp = document.getElementById('fabEncryptionKey');
var show = inp.type === 'password';
inp.type = show ? 'text' : 'password';
if (btn) { btn.textContent = show ? 'Elrejtés' : 'Megjelenítés'; }
@@ -452,7 +453,7 @@ function esc(s) { return String(s).replace(/[&<>"]/g, function(c){ return {'&':'
async function startExport() {
var drive = document.getElementById('destDrive').value;
var password = document.getElementById('exportPassword').value;
var password = document.getElementById('fabEncryptionKey').value;
var stopApp = document.getElementById('stopApp').checked;
document.getElementById('startBtn').disabled = true;
@@ -233,18 +233,6 @@
<div class="app-field-label">Éjszakai mentés</div>
<div class="app-field-value">Az alkalmazás adatbázisa és belső tárolói minden éjjel bekerülnek a mentésbe. <a href="/backups" class="app-info-link">Mentési állapot →</a></div>
</div>
<div class="app-field-row" data-backup-row="second">
<div class="app-field-label">2. mentés</div>
<div class="app-field-value">Kikapcsolva</div>
</div>
<div class="app-field-row" data-backup-row="target">
<div class="app-field-label">Cél</div>
<div class="app-field-value text-error">Nincs másik meghajtó, ahová másolhatna</div>
</div>
<div class="app-field-row">
<div class="app-field-label">Megjegyzés</div>
<div class="app-field-value">Nincs második meghajtó csatlakoztatva</div>
</div>
<p class="app-field-hint" style="margin-top:12px">A 2. mentés egy <strong>másik meghajtóra</strong> másolja az alkalmazás helyreállítási csomagját és adatait. A böngészhető fájljaidat csak ez védi meg egy meghajtóhiba ellen — a teljes rendszermentés ezeket nem tartalmazza.</p>
@@ -265,6 +253,9 @@
</select>
<div class="form-hint text-error" style="margin-top:.4rem" data-second-backup-notarget="1">Nincs másik meghajtó, ahová másolhatna — Nincs második meghajtó csatlakoztatva</div>
<div style="font-size:.8rem;color:var(--text-3);margin-top:.4rem">
Nincs másik adatmeghajtó — automatikusan a belső SSD-re kerül (csak az adatbázis és a beállítások). Egy 2. adatmeghajtóval a teljes adat is másik meghajtóra menthető.
</div>
@@ -233,18 +233,6 @@
<div class="app-field-label">Éjszakai mentés</div>
<div class="app-field-value">Az alkalmazás adatbázisa és belső tárolói minden éjjel bekerülnek a mentésbe. <a href="/backups" class="app-info-link">Mentési állapot →</a></div>
</div>
<div class="app-field-row" data-backup-row="second">
<div class="app-field-label">2. mentés</div>
<div class="app-field-value">Bekapcsolva</div>
</div>
<div class="app-field-row" data-backup-row="target">
<div class="app-field-label">Cél meghajtó</div>
<div class="app-field-value">HDD kettő</div>
</div>
<div class="app-field-row">
<div class="app-field-label">Kiválasztás módja</div>
<div class="app-field-value">automatikus — a legnagyobb szabad hely</div>
</div>
<p class="app-field-hint" style="margin-top:12px">A 2. mentés egy <strong>másik meghajtóra</strong> másolja az alkalmazás helyreállítási csomagját és adatait. A böngészhető fájljaidat csak ez védi meg egy meghajtóhiba ellen — a teljes rendszermentés ezeket nem tartalmazza.</p>
@@ -265,6 +253,7 @@
</select>
<div style="font-size:.8rem;color:var(--text-3);margin-top:.4rem">
Nincs másik adatmeghajtó — automatikusan a belső SSD-re kerül (csak az adatbázis és a beállítások). Egy 2. adatmeghajtóval a teljes adat is másik meghajtóra menthető.
</div>
@@ -233,18 +233,6 @@
<div class="app-field-label">Éjszakai mentés</div>
<div class="app-field-value">Az alkalmazás adatbázisa és belső tárolói minden éjjel bekerülnek a mentésbe. <a href="/backups" class="app-info-link">Mentési állapot →</a></div>
</div>
<div class="app-field-row" data-backup-row="second">
<div class="app-field-label">2. mentés</div>
<div class="app-field-value">Bekapcsolva</div>
</div>
<div class="app-field-row" data-backup-row="target">
<div class="app-field-label">Cél meghajtó</div>
<div class="app-field-value">SSD meghajtó egy — csak az adatbázis és a beállítások</div>
</div>
<div class="app-field-row">
<div class="app-field-label">Kiválasztás módja</div>
<div class="app-field-value">kézi választás — a leggyorsabb meghajtó</div>
</div>
<p class="app-field-hint" style="margin-top:12px">A 2. mentés egy <strong>másik meghajtóra</strong> másolja az alkalmazás helyreállítási csomagját és adatait. A böngészhető fájljaidat csak ez védi meg egy meghajtóhiba ellen — a teljes rendszermentés ezeket nem tartalmazza.</p>
@@ -271,6 +259,7 @@
</select>
</div>
<button type="submit" class="btn btn-primary">Mentés</button>
</form>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -251,26 +251,20 @@
<div class="form-section">
<h4>Automatikusan generált értékek</h4>
<p class="form-section-desc">Ezek az értékek a telepítéssel együtt mentésre kerülnek. Jegyezd fel a szükséges jelszavakat!</p>
<div class="form-group form-group-auto">
<label>Titkos kulcs érték <span class="auto-generated-badge"><svg class="ico ico-sm"><use href="#i-check"/></svg> Automatikusan generálva</span></label>
<div class="input-with-button">
<input type="password" id="auto-field-SECRET_KEY" class="form-control" value="generated-secret-value" readonly>
<button type="button" class="btn btn-sm btn-outline" onclick="toggleAutoField('auto-field-SECRET_KEY', this)">Megjelenítés</button>
</div>
<input type="hidden" name="SECRET_KEY" value="generated-secret-value">
@@ -300,8 +294,6 @@
<div class="form-section">
<h4>Beállítások</h4>
<div class="form-group">
<label for="field-SUBDOMAIN">
Webcím eleje
@@ -318,20 +310,15 @@
placeholder="aldomain"
pattern="[a-z0-9]([a-z0-9-]*[a-z0-9])?"
required
oninput="this.value=this.value.toLowerCase().replace(/[^a-z0-9-]/g,'')">
<span class="subdomain-suffix">.example.hu</span>
</div>
<span class="form-hint">Az aldomain telepítés után nem módosítható. Megváltoztatáshoz az alkalmazás eltávolítása és újratelepítése szükséges (minden adat törlődik).</span>
</div>
<div class="form-group">
<label for="field-LANG_SEL">
Felület nyelve
@@ -340,8 +327,7 @@
</label>
<select id="field-LANG_SEL" name="LANG_SEL" class="form-control"
>
<select id="field-LANG_SEL" name="LANG_SEL" class="form-control">
<option value="hu">Magyar nyelv</option>
@@ -351,8 +337,6 @@
</div>
<div class="form-group">
<label for="field-ADMIN_PASSWORD">
Admin jelszó mező
@@ -373,20 +357,16 @@
<button type="button" class="btn btn-sm btn-outline"
onclick="generatePassword('field-ADMIN_PASSWORD', 'field-confirm-ADMIN_PASSWORD', '')">Generálás</button>
</div>
<div class="input-with-button" style="margin-top:.25rem">
<input type="password" id="field-confirm-ADMIN_PASSWORD"
class="form-control" placeholder="Jelszó megerősítése"
data-confirm-for="field-ADMIN_PASSWORD">
</div>
</div>
<div class="form-group">
<label for="field-FLAG">
Kapcsoló mező itt
@@ -396,8 +376,7 @@
<label class="toggle">
<input type="checkbox" id="field-FLAG" name="FLAG" value="true"
>
<input type="checkbox" id="field-FLAG" name="FLAG" value="true">
<span class="toggle-label">Igen</span>
</label>
@@ -407,8 +386,6 @@
</div>
<div class="form-group">
<label for="field-HDD_PATH">
Adatok helye itt
@@ -419,7 +396,6 @@
<select id="field-HDD_PATH" name="HDD_PATH" class="form-control"
onchange="checkStorageSpace(this)">
<option value="/mnt/hdd1" data-free-percent="50"
@@ -443,7 +419,6 @@
HDD kettő — 100 GB szabad
</option>
</select>
<div id="storage-space-warn" class="form-hint" style="color:var(--warn);display:none">
<svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg> A kiválasztott tárhely majdnem megtelt.
@@ -458,8 +433,6 @@
</div>
<div class="form-group">
<label for="field-NOTE">
Megjegyzés mező
@@ -471,7 +444,6 @@
<input type="text" id="field-NOTE" name="NOTE"
class="form-control" value=""
placeholder="Írj ide valamit"
>
@@ -233,26 +233,20 @@
<div class="form-section">
<h4>Automatikusan generált értékek</h4>
<p class="form-section-desc">Ezek az értékek a telepítéssel együtt mentésre kerülnek. Jegyezd fel a szükséges jelszavakat!</p>
<div class="form-group form-group-auto">
<label>Titkos kulcs érték <span class="auto-generated-badge"><svg class="ico ico-sm"><use href="#i-check"/></svg> Automatikusan generálva</span></label>
<div class="input-with-button">
<input type="password" id="auto-field-SECRET_KEY" class="form-control" value="generated-secret-value" readonly>
<button type="button" class="btn btn-sm btn-outline" onclick="toggleAutoField('auto-field-SECRET_KEY', this)">Megjelenítés</button>
</div>
<input type="hidden" name="SECRET_KEY" value="generated-secret-value">
@@ -282,8 +276,6 @@
<div class="form-section">
<h4>Beállítások</h4>
<div class="form-group">
<label for="field-SUBDOMAIN">
Webcím eleje
@@ -300,20 +292,15 @@
placeholder="aldomain"
pattern="[a-z0-9]([a-z0-9-]*[a-z0-9])?"
required
oninput="this.value=this.value.toLowerCase().replace(/[^a-z0-9-]/g,'')">
<span class="subdomain-suffix">.example.hu</span>
</div>
<span class="form-hint">Az aldomain telepítés után nem módosítható. Megváltoztatáshoz az alkalmazás eltávolítása és újratelepítése szükséges (minden adat törlődik).</span>
</div>
<div class="form-group">
<label for="field-LANG_SEL">
Felület nyelve
@@ -322,8 +309,7 @@
</label>
<select id="field-LANG_SEL" name="LANG_SEL" class="form-control"
>
<select id="field-LANG_SEL" name="LANG_SEL" class="form-control">
<option value="hu">Magyar nyelv</option>
@@ -333,8 +319,6 @@
</div>
<div class="form-group">
<label for="field-ADMIN_PASSWORD">
Admin jelszó mező
@@ -355,20 +339,16 @@
<button type="button" class="btn btn-sm btn-outline"
onclick="generatePassword('field-ADMIN_PASSWORD', 'field-confirm-ADMIN_PASSWORD', '')">Generálás</button>
</div>
<div class="input-with-button" style="margin-top:.25rem">
<input type="password" id="field-confirm-ADMIN_PASSWORD"
class="form-control" placeholder="Jelszó megerősítése"
data-confirm-for="field-ADMIN_PASSWORD">
</div>
</div>
<div class="form-group">
<label for="field-FLAG">
Kapcsoló mező itt
@@ -378,8 +358,7 @@
<label class="toggle">
<input type="checkbox" id="field-FLAG" name="FLAG" value="true"
>
<input type="checkbox" id="field-FLAG" name="FLAG" value="true">
<span class="toggle-label">Igen</span>
</label>
@@ -389,8 +368,6 @@
</div>
<div class="form-group">
<label for="field-HDD_PATH">
Adatok helye itt
@@ -403,8 +380,7 @@
<input type="text" id="field-HDD_PATH" name="HDD_PATH"
class="form-control" value=""
placeholder="/mnt/valahol"
required
>
required>
<span class="form-hint" style="color:var(--warn)">Nincs regisztrált adattároló — add meg kézzel az útvonalat</span>
@@ -412,8 +388,6 @@
</div>
<div class="form-group">
<label for="field-NOTE">
Megjegyzés mező
@@ -425,7 +399,6 @@
<input type="text" id="field-NOTE" name="NOTE"
class="form-control" value=""
placeholder="Írj ide valamit"
>
@@ -228,26 +228,20 @@
<div class="form-section">
<h4>Automatikusan generált értékek</h4>
<p class="form-section-desc">Ezek az értékek a telepítéssel együtt mentésre kerülnek. Jegyezd fel a szükséges jelszavakat!</p>
<div class="form-group form-group-auto">
<label>Titkos kulcs érték <span class="auto-generated-badge"><svg class="ico ico-sm"><use href="#i-check"/></svg> Automatikusan generálva</span></label>
<div class="input-with-button">
<input type="password" id="auto-field-SECRET_KEY" class="form-control" value="generated-secret-value" readonly>
<button type="button" class="btn btn-sm btn-outline" onclick="toggleAutoField('auto-field-SECRET_KEY', this)">Megjelenítés</button>
</div>
<input type="hidden" name="SECRET_KEY" value="generated-secret-value">
@@ -277,8 +271,6 @@
<div class="form-section">
<h4>Beállítások</h4>
<div class="form-group">
<label for="field-SUBDOMAIN">
Webcím eleje
@@ -295,20 +287,15 @@
placeholder="aldomain"
pattern="[a-z0-9]([a-z0-9-]*[a-z0-9])?"
required
oninput="this.value=this.value.toLowerCase().replace(/[^a-z0-9-]/g,'')">
<span class="subdomain-suffix">.example.hu</span>
</div>
<span class="form-hint">Az aldomain telepítés után nem módosítható. Megváltoztatáshoz az alkalmazás eltávolítása és újratelepítése szükséges (minden adat törlődik).</span>
</div>
<div class="form-group">
<label for="field-LANG_SEL">
Felület nyelve
@@ -317,8 +304,7 @@
</label>
<select id="field-LANG_SEL" name="LANG_SEL" class="form-control"
>
<select id="field-LANG_SEL" name="LANG_SEL" class="form-control">
<option value="hu">Magyar nyelv</option>
@@ -328,8 +314,6 @@
</div>
<div class="form-group">
<label for="field-ADMIN_PASSWORD">
Admin jelszó mező
@@ -350,20 +334,16 @@
<button type="button" class="btn btn-sm btn-outline"
onclick="generatePassword('field-ADMIN_PASSWORD', 'field-confirm-ADMIN_PASSWORD', '')">Generálás</button>
</div>
<div class="input-with-button" style="margin-top:.25rem">
<input type="password" id="field-confirm-ADMIN_PASSWORD"
class="form-control" placeholder="Jelszó megerősítése"
data-confirm-for="field-ADMIN_PASSWORD">
</div>
</div>
<div class="form-group">
<label for="field-FLAG">
Kapcsoló mező itt
@@ -373,8 +353,7 @@
<label class="toggle">
<input type="checkbox" id="field-FLAG" name="FLAG" value="true"
>
<input type="checkbox" id="field-FLAG" name="FLAG" value="true">
<span class="toggle-label">Igen</span>
</label>
@@ -384,8 +363,6 @@
</div>
<div class="form-group">
<label for="field-HDD_PATH">
Adatok helye itt
@@ -396,7 +373,6 @@
<select id="field-HDD_PATH" name="HDD_PATH" class="form-control"
onchange="checkStorageSpace(this)">
<option value="/mnt/hdd1" data-free-percent="50"
@@ -420,9 +396,6 @@
HDD kettő — 100 GB szabad
</option>
<option value="/mnt/gone" selected disabled>/mnt/gone (nem elérhető)</option>
</select>
<div id="storage-space-warn" class="form-hint" style="color:var(--warn);display:none">
<svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg> A kiválasztott tárhely majdnem megtelt.
@@ -437,8 +410,6 @@
</div>
<div class="form-group">
<label for="field-NOTE">
Megjegyzés mező
@@ -450,7 +421,6 @@
<input type="text" id="field-NOTE" name="NOTE"
class="form-control" value=""
placeholder="Írj ide valamit"
>