// Svrnty plugin frontend — Hermes WebUI extensions. // Loaded via /plugins/svrnty/app.js (registered by plugin.py register_static). // Runs in WebUI origin with full session authority. Additive + idempotent. (function () { "use strict"; if (window.__svrntyExtLoaded) return; window.__svrntyExtLoaded = true; // ── Vault status panel (migrated from fork commit 3e2c74f3) ───────────── // Injects a "Vault connections" section into Settings → System on demand, // populates it from GET /api/vault/status (served by plugin/routes/vault_status.py). const VAULT_LABELS = { anthropic: "Anthropic", gitea: "Gitea", "keycloak-planb": "Keycloak (Plan B)", meta: "Meta", "google-ads": "Google Ads", "google-ai": "Google AI", "google-business": "Google Business", "google-search-console": "Search Console", quickbooks: "QuickBooks", "google-analytics": "Google Analytics", mailchimp: "Mailchimp", paypal: "PayPal", square: "Square", woocommerce: "WooCommerce", "wordpress-admin": "WordPress", agendrix: "Agendrix", perplexity: "Perplexity", wix: "Wix", }; function _injectVaultPanel() { // Already injected? if (document.getElementById("vaultStatusSection")) return true; // Anchor after the gateway-status card in System settings. const anchor = document.getElementById("gatewayStatusCard"); if (!anchor) return false; const section = document.createElement("div"); section.id = "vaultStatusSection"; section.style.marginTop = "16px"; section.innerHTML = '
' + '
Vault connections
' + '' + "
" + '
credctl-managed secrets — green = present, grey = absent
' + '
Loading…
'; anchor.parentNode.insertBefore(section, anchor.nextSibling); document.getElementById("vaultRefreshBtn").addEventListener("click", _loadVaultStatus); return true; } function _loadVaultStatus() { const list = document.getElementById("vaultStatusList"); if (!list) return; fetch("/api/vault/status") .then((r) => r.json()) .then((r) => { const present = new Set((r.secrets || []).map((s) => s.name)); const names = Object.keys(VAULT_LABELS); list.innerHTML = '
' + names.map((name) => { const ok = present.has(name); const color = ok ? "#22c55e" : "#6b7280"; const label = VAULT_LABELS[name] || name; return ( '' + `` + label.replace(/[<>&]/g, (c) => ({ "<": "<", ">": ">", "&": "&" }[c])) + "" ); }).join("") + "
"; }) .catch(() => { list.innerHTML = '
Failed to load vault status
'; }); } // Watch for the System settings tab opening; inject + load when it appears. // The panel exists in the DOM only after the user navigates Settings → System. function _hookSystemPanelOpen() { const observer = new MutationObserver(() => { if (_injectVaultPanel()) _loadVaultStatus(); }); observer.observe(document.body, { childList: true, subtree: true }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", _hookSystemPanelOpen); } else { _hookSystemPanelOpen(); } })();