"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.' + '

' + '' + '' + '
' + '
' + // ── Section B: Verify System Integrity ──────────────────── '
' + '

Verify System Integrity

' + '

' + '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:

' + '
    ' + '
  1. ' + 'Source Code Match \u2014 The system configuration on this machine matches ' + 'the exact commit published in the public repository. No hidden changes were added.' + '
  2. ' + '
  3. ' + '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.' + '
  4. ' + '
  5. ' + 'Running System Match \u2014 The currently running system matches what the ' + 'configuration says it should be. No unauthorized modifications are active.' + '
  6. ' + '
' + '

' + '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 += '
'; } html += '
'; verifyResults.innerHTML = html; } catch (err) { verifyResults.innerHTML = '

\u274C Verification failed: ' + escHtml(err.message || "Unknown error") + '

'; } verifyBtn.disabled = false; verifyBtn.textContent = "Verify Now"; }); } } }