Tier 0: render what the services already decided, honestly
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -25,30 +25,70 @@ Singleton {
|
||||
property var facts: []
|
||||
property bool scanned: false
|
||||
|
||||
// Why the last read produced nothing, when it produced nothing.
|
||||
//
|
||||
// A security readout with no facts is a read that failed, not a machine
|
||||
// with nothing to say, and the two are indistinguishable downstream:
|
||||
// attentionCount is 0 for an empty list exactly as it is for a clean one,
|
||||
// so a page reading only that would answer "everything is in its
|
||||
// recommended state" on top of a helper that never ran. The helper builds
|
||||
// its JSON with jq and prints `[]` when jq is missing, so this is a real
|
||||
// failure mode and not a hypothetical one.
|
||||
//
|
||||
// Read it against an empty `facts`: a read that produced facts AND wrote
|
||||
// something to stderr is a helper being chatty, not a failed check.
|
||||
property string lastError: ""
|
||||
|
||||
// The facts that are not in their reassuring state. The page leads with the
|
||||
// count so a machine that is entirely fine says so in one line instead of
|
||||
// making the user read five rows to find out.
|
||||
readonly property int attentionCount: root.facts.filter(fact => !fact.ok).length
|
||||
|
||||
function refresh(): void {
|
||||
if (!query.running)
|
||||
if (!query.running) {
|
||||
root.lastError = "";
|
||||
query.running = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Only fills in a reason nothing else has given, so whichever of stderr,
|
||||
// the exit code and the parse notices the failure first keeps the say.
|
||||
function blame(reason: string): void {
|
||||
if (root.lastError === "")
|
||||
root.lastError = reason;
|
||||
}
|
||||
|
||||
function absorb(text: string): void {
|
||||
const answer = text.trim();
|
||||
if (answer === "") {
|
||||
root.facts = [];
|
||||
root.blame("the security helper answered with nothing.");
|
||||
} else {
|
||||
try {
|
||||
const parsed = JSON.parse(answer);
|
||||
root.facts = Array.isArray(parsed) ? parsed : [];
|
||||
if (root.facts.length === 0)
|
||||
root.blame("the security helper reported no facts at all.");
|
||||
} catch (error) {
|
||||
root.facts = [];
|
||||
root.blame("the security helper's answer could not be read.");
|
||||
console.warn("DeviceSecurity: could not parse helper output:", error);
|
||||
}
|
||||
}
|
||||
root.scanned = true;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: query
|
||||
command: [root.helperPath]
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
try {
|
||||
const parsed = JSON.parse(this.text);
|
||||
root.facts = Array.isArray(parsed) ? parsed : [];
|
||||
} catch (error) {
|
||||
root.facts = [];
|
||||
console.warn("DeviceSecurity: could not parse helper output:", error);
|
||||
}
|
||||
root.scanned = true;
|
||||
}
|
||||
stdout: StdioCollector { onStreamFinished: root.absorb(this.text) }
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: if (this.text.trim() !== "") root.blame(this.text.trim())
|
||||
}
|
||||
onExited: (code, status) => {
|
||||
if (code !== 0)
|
||||
root.blame("the security helper exited with code " + code + ".");
|
||||
root.scanned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user