Render Runtime Health detail surface
This commit is contained in:
parent
114ffa4067
commit
f59b81b9e7
@ -74,3 +74,36 @@ main.main:not(.svrnty-showing-cortex-os) .cortex-os-runtime-health {
|
|||||||
.cortex-os-runtime-health__signals dd {
|
.cortex-os-runtime-health__signals dd {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cortex-os-runtime-health__details {
|
||||||
|
border-top: 1px solid rgba(19, 82, 121, 0.14);
|
||||||
|
display: grid;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 12px;
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cortex-os-runtime-health__detail-group h3 {
|
||||||
|
margin: 0 0 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cortex-os-runtime-health__detail-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(116px, 0.8fr) minmax(0, 1.2fr);
|
||||||
|
gap: 4px 10px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cortex-os-runtime-health__detail-list dt,
|
||||||
|
.cortex-os-runtime-health__detail-list dd {
|
||||||
|
margin: 0;
|
||||||
|
min-width: 0;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cortex-os-runtime-health__detail-list dt {
|
||||||
|
color: #44515f;
|
||||||
|
}
|
||||||
|
|||||||
@ -38,10 +38,15 @@
|
|||||||
list.className = "cortex-os-runtime-health__signals";
|
list.className = "cortex-os-runtime-health__signals";
|
||||||
list.setAttribute("data-role", "signals");
|
list.setAttribute("data-role", "signals");
|
||||||
|
|
||||||
|
var details = document.createElement("section");
|
||||||
|
details.className = "cortex-os-runtime-health__details";
|
||||||
|
details.setAttribute("data-role", "details");
|
||||||
|
|
||||||
panel.appendChild(title);
|
panel.appendChild(title);
|
||||||
panel.appendChild(badge);
|
panel.appendChild(badge);
|
||||||
panel.appendChild(summary);
|
panel.appendChild(summary);
|
||||||
panel.appendChild(list);
|
panel.appendChild(list);
|
||||||
|
panel.appendChild(details);
|
||||||
|
|
||||||
var target = document.querySelector("main.main");
|
var target = document.querySelector("main.main");
|
||||||
if (!target) {
|
if (!target) {
|
||||||
@ -51,13 +56,14 @@
|
|||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setState(panel, state, headline, detail, signals) {
|
function setState(panel, state, headline, detail, signals, payloadDetails) {
|
||||||
var nextState = states.indexOf(state) >= 0 ? state : "unknown";
|
var nextState = states.indexOf(state) >= 0 ? state : "unknown";
|
||||||
panel.setAttribute("data-state", nextState);
|
panel.setAttribute("data-state", nextState);
|
||||||
panel.querySelector("[data-role='headline']").textContent = headline || "Runtime Health";
|
panel.querySelector("[data-role='headline']").textContent = headline || "Runtime Health";
|
||||||
panel.querySelector("[data-role='status']").textContent = nextState;
|
panel.querySelector("[data-role='status']").textContent = nextState;
|
||||||
panel.querySelector("[data-role='summary']").textContent = detail || "redacted";
|
panel.querySelector("[data-role='summary']").textContent = detail || "redacted";
|
||||||
renderSignals(panel.querySelector("[data-role='signals']"), signals || []);
|
renderSignals(panel.querySelector("[data-role='signals']"), signals || []);
|
||||||
|
renderDetails(panel.querySelector("[data-role='details']"), payloadDetails || {});
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSignals(list, signals) {
|
function renderSignals(list, signals) {
|
||||||
@ -75,6 +81,69 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderKeyValues(container, title, rows) {
|
||||||
|
var group = document.createElement("section");
|
||||||
|
group.className = "cortex-os-runtime-health__detail-group";
|
||||||
|
|
||||||
|
var heading = document.createElement("h3");
|
||||||
|
heading.textContent = title;
|
||||||
|
group.appendChild(heading);
|
||||||
|
|
||||||
|
var list = document.createElement("dl");
|
||||||
|
list.className = "cortex-os-runtime-health__detail-list";
|
||||||
|
rows.forEach(function (row) {
|
||||||
|
var key = document.createElement("dt");
|
||||||
|
var value = document.createElement("dd");
|
||||||
|
key.textContent = row.key || "redacted";
|
||||||
|
value.textContent = row.value || "redacted";
|
||||||
|
list.appendChild(key);
|
||||||
|
list.appendChild(value);
|
||||||
|
});
|
||||||
|
group.appendChild(list);
|
||||||
|
container.appendChild(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderDetails(container, detail) {
|
||||||
|
container.textContent = "";
|
||||||
|
var signals = detail.signals || [];
|
||||||
|
var warnings = detail.warnings || [];
|
||||||
|
var redactions = detail.redactions || [];
|
||||||
|
var sourceTrace = detail.source_trace || [];
|
||||||
|
var authority = detail.authority || {};
|
||||||
|
var allAuthorityDenied = Object.keys(authority).every(function (key) {
|
||||||
|
return authority[key] === false;
|
||||||
|
});
|
||||||
|
|
||||||
|
renderKeyValues(container, "Signals", signals.slice(0, 3).map(function (signal) {
|
||||||
|
return {
|
||||||
|
key: signal.signal_id || "redacted",
|
||||||
|
value: (signal.state || "unknown") + " | " + (signal.redacted ? "redacted" : "visible") + " | " + (signal.summary || "redacted")
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
renderKeyValues(container, "Warnings", warnings.slice(0, 3).map(function (warning) {
|
||||||
|
return {
|
||||||
|
key: warning.code || "redacted",
|
||||||
|
value: warning.message || "redacted"
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
renderKeyValues(container, "Redactions", redactions.slice(0, 4).map(function (redaction) {
|
||||||
|
return {
|
||||||
|
key: redaction.reason_code || "redacted",
|
||||||
|
value: redaction.label || "redacted"
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
renderKeyValues(container, "Source Trace", sourceTrace.slice(0, 3).map(function (source) {
|
||||||
|
return {
|
||||||
|
key: source.source_kind || "redacted",
|
||||||
|
value: source.label || "redacted"
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
renderKeyValues(container, "Authority", [{
|
||||||
|
key: "all denied",
|
||||||
|
value: allAuthorityDenied ? "true" : "review required"
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
function renderPayload(panel, payload) {
|
function renderPayload(panel, payload) {
|
||||||
if (!payload || payload.ok !== true || !payload.result) {
|
if (!payload || payload.ok !== true || !payload.result) {
|
||||||
setState(panel, "error", "Runtime Health is unavailable.", "Runtime Health is unavailable.", []);
|
setState(panel, "error", "Runtime Health is unavailable.", "Runtime Health is unavailable.", []);
|
||||||
@ -87,6 +156,13 @@
|
|||||||
displaySummary.headline,
|
displaySummary.headline,
|
||||||
displaySummary.detail,
|
displaySummary.detail,
|
||||||
payload.result.signals,
|
payload.result.signals,
|
||||||
|
{
|
||||||
|
signals: payload.result.signals,
|
||||||
|
warnings: payload.result.warnings,
|
||||||
|
redactions: payload.result.redactions,
|
||||||
|
source_trace: payload.result.source_trace,
|
||||||
|
authority: payload.result.authority
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,10 @@ def test_runtime_health_display_has_no_hidden_write_surface():
|
|||||||
"window.open",
|
"window.open",
|
||||||
"eval(",
|
"eval(",
|
||||||
"new Function",
|
"new Function",
|
||||||
|
"JSON.stringify",
|
||||||
|
"Object.keys(payload",
|
||||||
|
"Object.entries(payload",
|
||||||
|
"clipboard",
|
||||||
"innerHTML",
|
"innerHTML",
|
||||||
"insertAdjacentHTML",
|
"insertAdjacentHTML",
|
||||||
"outerHTML",
|
"outerHTML",
|
||||||
@ -85,6 +89,10 @@ def test_runtime_health_display_consumes_canonical_envelope_only():
|
|||||||
"signal.signal_id",
|
"signal.signal_id",
|
||||||
"signal.state",
|
"signal.state",
|
||||||
"signal.summary",
|
"signal.summary",
|
||||||
|
"payload.result.warnings",
|
||||||
|
"payload.result.redactions",
|
||||||
|
"payload.result.source_trace",
|
||||||
|
"payload.result.authority",
|
||||||
]:
|
]:
|
||||||
assert snippet in js
|
assert snippet in js
|
||||||
for forbidden in [
|
for forbidden in [
|
||||||
@ -101,3 +109,30 @@ def test_runtime_health_display_consumes_canonical_envelope_only():
|
|||||||
"authority.delegated_memory_grant",
|
"authority.delegated_memory_grant",
|
||||||
]:
|
]:
|
||||||
assert forbidden not in js
|
assert forbidden not in js
|
||||||
|
|
||||||
|
|
||||||
|
def test_runtime_health_detail_surface_is_bounded_and_text_only():
|
||||||
|
js = JS.read_text(encoding="utf-8")
|
||||||
|
css = CSS.read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
for snippet in [
|
||||||
|
'details.setAttribute("data-role", "details")',
|
||||||
|
"renderDetails(",
|
||||||
|
"renderKeyValues(",
|
||||||
|
"signals.slice(0, 3)",
|
||||||
|
"warnings.slice(0, 3)",
|
||||||
|
"redactions.slice(0, 4)",
|
||||||
|
"sourceTrace.slice(0, 3)",
|
||||||
|
"allAuthorityDenied",
|
||||||
|
".every(function (key)",
|
||||||
|
"textContent",
|
||||||
|
]:
|
||||||
|
assert snippet in js
|
||||||
|
for snippet in [
|
||||||
|
".cortex-os-runtime-health__details",
|
||||||
|
".cortex-os-runtime-health__detail-group",
|
||||||
|
".cortex-os-runtime-health__detail-list",
|
||||||
|
]:
|
||||||
|
assert snippet in css
|
||||||
|
for forbidden in ["body {", "main {", "#app", ".panel"]:
|
||||||
|
assert forbidden not in css
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user