@glassmkr/crucible 0.13.13 → 0.13.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,49 @@
1
+ // Tests for parseWtmp: the clean-shutdown detection that feeds the dashboard's
2
+ // unexpected_reboot rule. Regression for the round-3 false positive where a
3
+ // deliberate `sudo reboot` was reported as an unclean shutdown because the old
4
+ // `last shutdown -F` command returns nothing on modern systemd/util-linux.
5
+ import { describe, expect, it } from "vitest";
6
+ import { parseWtmp } from "../reboot-evidence.js";
7
+ // Real `last -x -F` shapes (most-recent-first).
8
+ const CLEAN = `reboot system boot 6.17.0-35-generic Sat Jun 27 19:22:28 2026 still running
9
+ shutdown system down 6.17.0-23-generic Sat Jun 27 19:20:39 2026 - Sat Jun 27 19:22:28 2026 (00:01)
10
+ reboot system boot 6.17.0-23-generic Wed May 20 21:32:36 2026 - Sat Jun 27 19:20:39 2026 (37+21:48)
11
+
12
+ wtmp begins Tue Apr 7 22:14:51 2026`;
13
+ const UNCLEAN = `reboot system boot 6.17.0-35-generic Sat Jun 27 19:22:28 2026 still running
14
+ reboot system boot 6.17.0-23-generic Wed May 20 21:32:36 2026 - Sat Jun 27 19:22:00 2026 (37+21:49)
15
+
16
+ wtmp begins Tue Apr 7 22:14:51 2026`;
17
+ // runlevel + user-login records interleave in real output; the parser must
18
+ // filter to reboot/shutdown system lines before checking adjacency.
19
+ const CLEAN_INTERLEAVED = `simon pts/0 198.51.100.4 Sat Jun 27 20:00:00 2026 still logged in
20
+ runlevel (to lvl 5) 6.17.0-35-generic Sat Jun 27 19:22:30 2026 still running
21
+ reboot system boot 6.17.0-35-generic Sat Jun 27 19:22:28 2026 still running
22
+ shutdown system down 6.17.0-23-generic Sat Jun 27 19:20:39 2026 - Sat Jun 27 19:22:28 2026 (00:01)
23
+ reboot system boot 6.17.0-23-generic Wed May 20 21:32:36 2026 - Sat Jun 27 19:20:39 2026 (37+21:48)`;
24
+ describe("parseWtmp", () => {
25
+ it("clean: a shutdown record immediately before the most recent boot", () => {
26
+ const r = parseWtmp(CLEAN);
27
+ expect(r.prior_shutdown_clean).toBe(true);
28
+ expect(r.last_reboot_raw).toContain("reboot");
29
+ expect(r.last_reboot_raw).toContain("6.17.0-35");
30
+ });
31
+ it("unclean: two boots back-to-back with no shutdown between (hard reset)", () => {
32
+ const r = parseWtmp(UNCLEAN);
33
+ expect(r.prior_shutdown_clean).toBe(false);
34
+ expect(r.last_reboot_raw).toContain("6.17.0-35");
35
+ });
36
+ it("clean even when runlevel and login records interleave", () => {
37
+ expect(parseWtmp(CLEAN_INTERLEAVED).prior_shutdown_clean).toBe(true);
38
+ });
39
+ it("empty / no system records: not clean, null reboot", () => {
40
+ expect(parseWtmp("")).toEqual({ last_reboot_raw: null, prior_shutdown_clean: false });
41
+ expect(parseWtmp("wtmp begins Tue Apr 7 22:14:51 2026").prior_shutdown_clean).toBe(false);
42
+ });
43
+ it("first boot ever (single reboot, no prior shutdown) is not clean", () => {
44
+ const r = parseWtmp("reboot system boot 6.17.0-35-generic Sat Jun 27 19:22:28 2026 still running");
45
+ expect(r.prior_shutdown_clean).toBe(false);
46
+ expect(r.last_reboot_raw).toContain("reboot");
47
+ });
48
+ });
49
+ //# sourceMappingURL=reboot-evidence.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reboot-evidence.test.js","sourceRoot":"","sources":["../../../src/collect/__tests__/reboot-evidence.test.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,4EAA4E;AAC5E,+EAA+E;AAC/E,2EAA2E;AAE3E,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,gDAAgD;AAChD,MAAM,KAAK,GAAG;;;;qCAIuB,CAAC;AAEtC,MAAM,OAAO,GAAG;;;qCAGqB,CAAC;AAEtC,2EAA2E;AAC3E,oEAAoE;AACpE,MAAM,iBAAiB,GAAG;;;;uGAI6E,CAAC;AAExG,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAC3B,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC,CAAC;QACtF,MAAM,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,CAAC,GAAG,SAAS,CAAC,kFAAkF,CAAC,CAAC;QACxG,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +1,28 @@
1
1
  import type { RebootEvidence } from "../lib/types.js";
2
+ interface WtmpRebootRecord {
3
+ /** Last `reboot` line, e.g. "reboot system boot 5.15.0 Wed May 13 05:21:17 2026 still running". */
4
+ last_reboot_raw: string | null;
5
+ /** True if the wtmp log shows a `shutdown` record immediately before
6
+ * the most recent reboot; false if only the reboot is present
7
+ * (suggests power loss or hard reset). */
8
+ prior_shutdown_clean: boolean;
9
+ }
10
+ /**
11
+ * Parse `last -x -F` output into the reboot record. Pure; exported for tests.
12
+ *
13
+ * The `-x` flag is essential: it surfaces the `shutdown` and `runlevel` system
14
+ * pseudo-records. Plain `last reboot` / `last shutdown` do NOT show the
15
+ * shutdown record on modern systemd + util-linux (verified on Ubuntu, 6.17
16
+ * kernels): `last shutdown` returns nothing even after a clean `sudo reboot`,
17
+ * which made prior_shutdown_clean false on EVERY clean reboot and escalated
18
+ * deliberate reboots to a critical "unclean-shutdown" alert (false positive).
19
+ *
20
+ * Output is most-recent-first. We keep only the `reboot`/`shutdown` system
21
+ * lines so interleaved `runlevel` and user-login records do not break
22
+ * adjacency. The most recent boot was clean iff a `shutdown` record sits
23
+ * immediately before it (the next system record). No shutdown before the boot
24
+ * means a hard reset / power loss / panic.
25
+ */
26
+ export declare function parseWtmp(output: string): WtmpRebootRecord;
2
27
  export declare function collectRebootEvidence(): Promise<RebootEvidence>;
28
+ export {};
@@ -61,33 +61,38 @@ function vmcorePresent() {
61
61
  return false;
62
62
  }
63
63
  }
64
+ /**
65
+ * Parse `last -x -F` output into the reboot record. Pure; exported for tests.
66
+ *
67
+ * The `-x` flag is essential: it surfaces the `shutdown` and `runlevel` system
68
+ * pseudo-records. Plain `last reboot` / `last shutdown` do NOT show the
69
+ * shutdown record on modern systemd + util-linux (verified on Ubuntu, 6.17
70
+ * kernels): `last shutdown` returns nothing even after a clean `sudo reboot`,
71
+ * which made prior_shutdown_clean false on EVERY clean reboot and escalated
72
+ * deliberate reboots to a critical "unclean-shutdown" alert (false positive).
73
+ *
74
+ * Output is most-recent-first. We keep only the `reboot`/`shutdown` system
75
+ * lines so interleaved `runlevel` and user-login records do not break
76
+ * adjacency. The most recent boot was clean iff a `shutdown` record sits
77
+ * immediately before it (the next system record). No shutdown before the boot
78
+ * means a hard reset / power loss / panic.
79
+ */
80
+ export function parseWtmp(output) {
81
+ const sysLines = output
82
+ .split("\n")
83
+ .map((l) => l.trim())
84
+ .filter((l) => l.startsWith("reboot") || l.startsWith("shutdown"));
85
+ const lastReboot = sysLines[0]?.startsWith("reboot") ? sysLines[0] : null;
86
+ const prior_shutdown_clean = sysLines[0]?.startsWith("reboot") === true &&
87
+ sysLines[1]?.startsWith("shutdown") === true;
88
+ return { last_reboot_raw: lastReboot, prior_shutdown_clean };
89
+ }
64
90
  async function readWtmp() {
65
- const output = await run("last", ["reboot", "-F"], 5000);
91
+ const output = await run("last", ["-x", "-F"], 5000);
66
92
  if (!output) {
67
93
  return { last_reboot_raw: null, prior_shutdown_clean: false };
68
94
  }
69
- const lines = output.split("\n").filter((l) => l.trim().length > 0);
70
- // The first non-empty line is the most recent reboot record.
71
- const lastReboot = lines[0] ?? null;
72
- // Look for a `shutdown` record between the most recent reboot and
73
- // the second-most-recent reboot. `last -F` interleaves shutdown
74
- // records when present; on a clean shutdown they sit immediately
75
- // before the boot record.
76
- const shutdownOutput = await run("last", ["shutdown", "-F"], 5000);
77
- let priorShutdownClean = false;
78
- if (shutdownOutput && lastReboot) {
79
- // Extract a date marker from the lastReboot line; if any shutdown
80
- // record predates this reboot by <= 5 minutes, treat as clean.
81
- // Conservative: if any shutdown record exists in the wtmp at all,
82
- // assume the most recent one was clean. Defensive against parsing
83
- // glitches; refined by the dashboard evaluator.
84
- const sLines = shutdownOutput.split("\n").filter((l) => l.trim().length > 0 && l.startsWith("shutdown"));
85
- priorShutdownClean = sLines.length > 0;
86
- }
87
- return {
88
- last_reboot_raw: lastReboot,
89
- prior_shutdown_clean: priorShutdownClean,
90
- };
95
+ return parseWtmp(output);
91
96
  }
92
97
  export async function collectRebootEvidence() {
93
98
  const records = pstoreRecords();
@@ -1 +1 @@
1
- {"version":3,"file":"reboot-evidence.js","sourceRoot":"","sources":["../../src/collect/reboot-evidence.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,kEAAkE;AAClE,EAAE;AACF,kDAAkD;AAClD,EAAE;AACF,iEAAiE;AACjE,8DAA8D;AAC9D,iEAAiE;AACjE,4BAA4B;AAC5B,EAAE;AACF,8DAA8D;AAC9D,8DAA8D;AAC9D,yCAAyC;AACzC,EAAE;AACF,mEAAmE;AACnE,+DAA+D;AAC/D,kEAAkE;AAClE,+DAA+D;AAC/D,0DAA0D;AAC1D,EAAE;AACF,iEAAiE;AACjE,2DAA2D;AAC3D,kEAAkE;AAClE,gBAAgB;AAEhB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,MAAM,WAAW,GAAG,gBAAgB,CAAC;AACrC,MAAM,cAAc,GAAG,YAAY,CAAC;AAEpC,SAAS,aAAa;IACpB,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CACrF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa;IACpB,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC;YAAE,OAAO,KAAK,CAAC;QAC9C,+DAA+D;QAC/D,gEAAgE;QAChE,iEAAiE;QACjE,0CAA0C;QAC1C,MAAM,GAAG,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,GAAG,cAAc,IAAI,GAAG,EAAE,CAAC;gBAC3C,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAC7B,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE;oBAAE,SAAS;gBAChC,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;gBACtC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,aAAa,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;oBAC3F,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAWD,KAAK,UAAU,QAAQ;IACrB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;IAChE,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACpE,6DAA6D;IAC7D,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACpC,kEAAkE;IAClE,gEAAgE;IAChE,iEAAiE;IACjE,0BAA0B;IAC1B,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IACnE,IAAI,kBAAkB,GAAG,KAAK,CAAC;IAC/B,IAAI,cAAc,IAAI,UAAU,EAAE,CAAC;QACjC,kEAAkE;QAClE,+DAA+D;QAC/D,kEAAkE;QAClE,kEAAkE;QAClE,gDAAgD;QAChD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QACzG,kBAAkB,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACzC,CAAC;IACD,OAAO;QACL,eAAe,EAAE,UAAU;QAC3B,oBAAoB,EAAE,kBAAkB;KACzC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,OAAO;QACL,cAAc,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC;QAClC,mBAAmB,EAAE,OAAO,CAAC,MAAM;QACnC,cAAc,EAAE,MAAM;QACtB,kBAAkB,EAAE,IAAI,CAAC,eAAe;QACxC,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;KAChD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"reboot-evidence.js","sourceRoot":"","sources":["../../src/collect/reboot-evidence.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glassmkr/crucible",
3
- "version": "0.13.13",
3
+ "version": "0.13.14",
4
4
  "description": "Lightweight bare metal server monitoring. IPMI, SMART, OS, network. Opinionated alerts.",
5
5
  "type": "module",
6
6
  "engines": {