"use strict";
// ── Security Modal ────────────────────────────────────────────────
function openSecurityModal() {
if ($supportModal) $supportModal.classList.add("open");
var title = document.getElementById("support-modal-title");
if (title) title.textContent = "\uD83D\uDEE1 Security";
if ($supportBody) {
$supportBody.innerHTML =
// ── Section A: Security Reset ──────────────────────────────
'
' +
'
Security Reset
' +
'
' +
'Run this if you are using this physical computer for the first time AND ' +
'it was not set up by you. This will complete the security setup by resetting all passwords ' +
'and your Bitcoin Lightning Node\u2019s private keys.' +
'
' +
'
' +
'You can also run this if you wish to reset all your passwords and your Bitcoin Lightning ' +
'Node\u2019s private keys. If you have not transferred the Bitcoin out of this node and did ' +
'not back up the private keys, you will lose your Bitcoin.' +
'
' +
'' +
'
' +
'
' +
'
' +
'\u26A0\uFE0F This will permanently delete:' +
'
' +
'
' +
'
All generated passwords and SSH keys
' +
'
LND wallet data (seed words, channels, macaroons)
' +
'
Application databases
' +
'
Vaultwarden data
' +
'
' +
'
You will go through onboarding again. This cannot be undone.
' +
'Your Sovran_SystemsOS is built with NixOS \u2014 a system designed for complete transparency ' +
'and reproducibility. Every piece of software on this machine is built from publicly auditable ' +
'source code and verified using cryptographic hashes.' +
'
' +
'
This verification confirms three things:
' +
'' +
'
' +
'Source Code Match \u2014 The system configuration on this machine matches ' +
'the exact commit published in the public repository. No hidden changes were added.' +
'
' +
'
' +
'Binary Integrity \u2014 Every installed package in the system store is ' +
'verified against its expected cryptographic hash. If any binary, library, or config file ' +
'was tampered with, it will be detected.' +
'
' +
'
' +
'Running System Match \u2014 The currently running system matches what the ' +
'configuration says it should be. No unauthorized modifications are active.' +
'
' +
'' +
'
' +
'In short: if this verification passes, you can be confident that the software running on ' +
'your machine is exactly what is published \u2014 nothing more, nothing less.' +
'
' +
'' +
'' +
'
';
// ── Wire Security Reset flow
var resetOpenBtn = document.getElementById("security-reset-open-btn");
var resetConfirmDiv = document.getElementById("security-reset-confirm");
var eraseInput = document.getElementById("security-erase-input");
var resetConfirmBtn = document.getElementById("security-reset-confirm-btn");
var resetCancelBtn = document.getElementById("security-reset-cancel-btn");
var resetStatus = document.getElementById("security-reset-status");
if (resetOpenBtn) {
resetOpenBtn.addEventListener("click", function() {
resetOpenBtn.style.display = "none";
if (resetConfirmDiv) resetConfirmDiv.style.display = "";
if (eraseInput) eraseInput.focus();
});
}
if (eraseInput && resetConfirmBtn) {
eraseInput.addEventListener("input", function() {
resetConfirmBtn.disabled = eraseInput.value.trim() !== "ERASE";
});
}
if (resetCancelBtn) {
resetCancelBtn.addEventListener("click", function() {
if (resetConfirmDiv) resetConfirmDiv.style.display = "none";
if (resetOpenBtn) resetOpenBtn.style.display = "";
if (eraseInput) eraseInput.value = "";
if (resetConfirmBtn) resetConfirmBtn.disabled = true;
if (resetStatus) { resetStatus.textContent = ""; resetStatus.className = "security-status-msg"; }
});
}
if (resetConfirmBtn) {
resetConfirmBtn.addEventListener("click", async function() {
if (!eraseInput || eraseInput.value.trim() !== "ERASE") return;
resetConfirmBtn.disabled = true;
resetConfirmBtn.textContent = "Erasing\u2026";
if (resetStatus) { resetStatus.textContent = "Running security reset\u2026"; resetStatus.className = "security-status-msg security-status-info"; }
try {
await apiFetch("/api/security/reset", { method: "POST" });
if (resetStatus) { resetStatus.textContent = "\u2713 Reset complete. Rebooting\u2026"; resetStatus.className = "security-status-msg security-status-ok"; }
if ($rebootOverlay) $rebootOverlay.classList.add("open");
} catch (err) {
if (resetStatus) { resetStatus.textContent = "\u2717 Error: " + (err.message || "Reset failed."); resetStatus.className = "security-status-msg security-status-error"; }
resetConfirmBtn.disabled = false;
resetConfirmBtn.textContent = "Erase & Reset";
}
});
}
// ── Wire Verify System Integrity
var verifyBtn = document.getElementById("security-verify-btn");
var verifyResults = document.getElementById("security-verify-results");
if (verifyBtn && verifyResults) {
verifyBtn.addEventListener("click", async function() {
verifyBtn.disabled = true;
verifyBtn.textContent = "Verifying\u2026";
verifyResults.style.display = "";
verifyResults.innerHTML = '
\u231B Running verification checks\u2026 This may take a few minutes.
';
try {
var data = await apiFetch("/api/security/verify-integrity", { method: "POST" });
var html = '
';
// Flake commit
html += '
';
html += 'Source Commit:';
html += '' + escHtml(data.flake_commit || "unknown") + '';
if (data.repo_url) {
html += 'View on Gitea \u2197';
}
html += '
';
// Store verification
var storeOk = data.store_verified === true;
html += '
';
html += 'Binary Integrity:';
html += '';
html += storeOk ? "\u2705 PASS" : "\u274C FAIL";
html += '';
html += '
';
if (!storeOk && data.store_errors && data.store_errors.length > 0) {
html += 'Show errors (' + data.store_errors.length + ')';
html += '
' + escHtml(data.store_errors.join("\n")) + '
';
html += '';
}
// System match
var sysOk = data.system_matches === true;
html += '
';
html += 'Running System Match:';
html += '';
html += sysOk ? "\u2705 PASS" : "\u274C FAIL";
html += '';
html += '
';
if (!sysOk) {
html += '
';
html += 'Current:' + escHtml(data.current_system_path || "") + '';
html += '
';
html += '
';
html += 'Expected:' + escHtml(data.expected_system_path || "") + '';
html += '