diff --git a/example_app/ui/index.html b/example_app/ui/index.html
index 7a2d595..43b8198 100644
--- a/example_app/ui/index.html
+++ b/example_app/ui/index.html
@@ -542,6 +542,14 @@
AI Security Command Center
Admin JWT:
+
@@ -699,7 +707,9 @@ Evidence & ABOM
const activityEl = document.getElementById("activity");
const demoBannerEl = document.getElementById("demoBanner");
const topRisksEl = document.getElementById("topRisks");
+ const dataSourceEl = document.getElementById("dataSource");
const tokenKey = "ocpa_admin_token";
+ const dataSourceKey = "ocpa_data_source";
let demoMode = false;
function setStatus(msg) {
@@ -806,6 +816,17 @@ Evidence & ABOM
return localStorage.getItem(tokenKey) || "";
}
+ function getDataSource() {
+ return localStorage.getItem(dataSourceKey) || "auto";
+ }
+
+ function setDataSource(value) {
+ localStorage.setItem(dataSourceKey, value);
+ if (dataSourceEl) {
+ dataSourceEl.value = value;
+ }
+ }
+
function authHeaders() {
const token = getToken();
if (!token) {
@@ -1200,6 +1221,7 @@ Evidence & ABOM
let summaryFallback = false;
let demoInjected = false;
let demoEvents = null;
+ const dataMode = getDataSource();
try {
const health = await fetchJson("/health");
renderOpaStatus(health.opa_status);
@@ -1245,52 +1267,67 @@ Evidence & ABOM
errors.push(`inventory: ${err.message}`);
}
- try {
- const summary = await fetchJson("/risk/summary?limit=500", true);
- renderSummary(document.getElementById("summary"), summary);
- } catch (err) {
- summaryError = err;
- summaryFallback = demoMode;
- if (!demoMode) {
- errors.push(`summary: ${err.message}`);
- if (summaryMetaEl && /401|403/.test(err.message)) {
- summaryMetaEl.textContent = "Admin JWT required to view counts.";
- }
- if (postureBadgeEl) {
- postureBadgeEl.textContent = "Locked";
- postureBadgeEl.className = "posture-value posture-locked";
- }
- if (postureSignalsEl) {
- postureSignalsEl.textContent = "Signals in window: --";
+ if (dataMode === "demo") {
+ demoInjected = true;
+ demoEvents = buildDemoEvents();
+ renderSummary(document.getElementById("summary"), buildDemoSummary(demoEvents));
+ } else {
+ try {
+ const summary = await fetchJson("/risk/summary?limit=500", true);
+ renderSummary(document.getElementById("summary"), summary);
+ } catch (err) {
+ summaryError = err;
+ summaryFallback = demoMode && dataMode === "auto";
+ if (!(demoMode && dataMode === "auto")) {
+ errors.push(`summary: ${err.message}`);
+ if (summaryMetaEl && /401|403/.test(err.message)) {
+ summaryMetaEl.textContent = "Admin JWT required to view counts.";
+ }
+ if (postureBadgeEl) {
+ postureBadgeEl.textContent = "Locked";
+ postureBadgeEl.className = "posture-value posture-locked";
+ }
+ if (postureSignalsEl) {
+ postureSignalsEl.textContent = "Signals in window: --";
+ }
}
}
}
- try {
- const ledger = await fetchJson("/ui/ledger?limit=200", true);
- if (demoMode && (!ledger.events || ledger.events.length === 0)) {
- demoInjected = true;
- demoEvents = buildDemoEvents();
- renderLedger(document.getElementById("ledger-body"), demoEvents);
- renderRiskDrivers(demoEvents);
- renderActivity(demoEvents);
- renderTopRisks(demoEvents);
- } else {
- renderLedger(document.getElementById("ledger-body"), ledger.events);
- renderRiskDrivers(ledger.events);
- renderActivity(ledger.events);
- renderTopRisks(ledger.events);
- }
- } catch (err) {
- if (demoMode) {
- demoInjected = true;
- demoEvents = buildDemoEvents();
- renderLedger(document.getElementById("ledger-body"), demoEvents);
- renderRiskDrivers(demoEvents);
- renderActivity(demoEvents);
- renderTopRisks(demoEvents);
- } else {
- errors.push(`ledger: ${err.message}`);
+ if (dataMode === "demo") {
+ demoInjected = true;
+ demoEvents = demoEvents || buildDemoEvents();
+ renderLedger(document.getElementById("ledger-body"), demoEvents);
+ renderRiskDrivers(demoEvents);
+ renderActivity(demoEvents);
+ renderTopRisks(demoEvents);
+ } else {
+ try {
+ const ledger = await fetchJson("/ui/ledger?limit=200", true);
+ if (dataMode === "auto" && demoMode && (!ledger.events || ledger.events.length === 0)) {
+ demoInjected = true;
+ demoEvents = buildDemoEvents();
+ renderLedger(document.getElementById("ledger-body"), demoEvents);
+ renderRiskDrivers(demoEvents);
+ renderActivity(demoEvents);
+ renderTopRisks(demoEvents);
+ } else {
+ renderLedger(document.getElementById("ledger-body"), ledger.events);
+ renderRiskDrivers(ledger.events);
+ renderActivity(ledger.events);
+ renderTopRisks(ledger.events);
+ }
+ } catch (err) {
+ if (demoMode && dataMode === "auto") {
+ demoInjected = true;
+ demoEvents = buildDemoEvents();
+ renderLedger(document.getElementById("ledger-body"), demoEvents);
+ renderRiskDrivers(demoEvents);
+ renderActivity(demoEvents);
+ renderTopRisks(demoEvents);
+ } else {
+ errors.push(`ledger: ${err.message}`);
+ }
}
}
@@ -1318,10 +1355,18 @@ Evidence & ABOM
errors.push(`summary: ${summaryError.message}`);
}
+ const sourceLabel =
+ demoInjected || dataMode === "demo"
+ ? "demo"
+ : dataMode === "live"
+ ? "live"
+ : demoMode
+ ? "auto"
+ : "live";
if (errors.length) {
- setStatus(`Updated with warnings: ${errors.join(" | ")}`);
+ setStatus(`Updated (${sourceLabel}) with warnings: ${errors.join(" | ")}`);
} else {
- setStatus(demoInjected ? "Updated (demo data active)." : "Updated.");
+ setStatus(`Updated (${sourceLabel}).`);
}
if (lastUpdatedEl) {
lastUpdatedEl.textContent = `Last refresh: ${new Date().toLocaleTimeString()}`;
@@ -1385,6 +1430,13 @@ Evidence & ABOM
document.getElementById("downloadOpenApi").addEventListener("click", () => downloadOpenApi("json"));
tokenEl.value = getToken();
+ if (dataSourceEl) {
+ dataSourceEl.value = getDataSource();
+ dataSourceEl.addEventListener("change", (event) => {
+ setDataSource(event.target.value);
+ refreshAll();
+ });
+ }
refreshAll();