@glassmkr/crucible 0.1.0 → 0.3.1

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.
Files changed (45) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +24 -0
  2. package/.github/ISSUE_TEMPLATE/no_data.md +26 -0
  3. package/README.md +48 -52
  4. package/dist/alerts/rules.js +120 -0
  5. package/dist/alerts/rules.js.map +1 -1
  6. package/dist/collect/cpu.js +57 -16
  7. package/dist/collect/cpu.js.map +1 -1
  8. package/dist/collect/disks.js +48 -2
  9. package/dist/collect/disks.js.map +1 -1
  10. package/dist/collect/ipmi.js +160 -2
  11. package/dist/collect/ipmi.js.map +1 -1
  12. package/dist/collect/security.d.ts +39 -0
  13. package/dist/collect/security.js +176 -0
  14. package/dist/collect/security.js.map +1 -0
  15. package/dist/config.d.ts +23 -0
  16. package/dist/config.js +5 -0
  17. package/dist/config.js.map +1 -1
  18. package/dist/index.js +48 -3
  19. package/dist/index.js.map +1 -1
  20. package/dist/lib/types.d.ts +64 -0
  21. package/dist/lib/version-check.d.ts +7 -0
  22. package/dist/lib/version-check.js +39 -0
  23. package/dist/lib/version-check.js.map +1 -0
  24. package/dist/metrics-server.d.ts +3 -0
  25. package/dist/metrics-server.js +113 -0
  26. package/dist/metrics-server.js.map +1 -0
  27. package/dist/notify/telegram.js +27 -9
  28. package/dist/notify/telegram.js.map +1 -1
  29. package/dist/push/forge.d.ts +1 -0
  30. package/dist/push/forge.js +80 -4
  31. package/dist/push/forge.js.map +1 -1
  32. package/package.json +1 -1
  33. package/scripts/sign-release.sh +29 -0
  34. package/src/alerts/rules.ts +99 -0
  35. package/src/collect/cpu.ts +64 -16
  36. package/src/collect/disks.ts +57 -2
  37. package/src/collect/ipmi.ts +147 -3
  38. package/src/collect/security.ts +238 -0
  39. package/src/config.ts +5 -0
  40. package/src/index.ts +49 -3
  41. package/src/lib/types.ts +44 -0
  42. package/src/lib/version-check.ts +38 -0
  43. package/src/metrics-server.ts +123 -0
  44. package/src/notify/telegram.ts +29 -9
  45. package/src/push/forge.ts +89 -5
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,8BAA8B,CAAC;AACrE,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;AAEtC,OAAO,CAAC,GAAG,CAAC,iCAAiC,MAAM,CAAC,WAAW,eAAe,MAAM,CAAC,UAAU,CAAC,gBAAgB,GAAG,CAAC,CAAC;AACrH,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,YAAY,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;AAChJ,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;AAE1F,MAAM,SAAS,GAAa,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC;AAEtI,KAAK,UAAU,OAAO;IACpB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAEzC,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC3F,aAAa,EAAE;QACf,UAAU,EAAE;QACZ,aAAa,EAAE;QACf,YAAY,EAAE;QACd,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,cAAc,EAAE;QAChB,WAAW,EAAE;QACb,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QACnE,eAAe,EAAE;KAClB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAa;QACzB,iBAAiB,EAAE,OAAO;QAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ;KAC5E,CAAC;IAEF,kBAAkB;IAClB,MAAM,YAAY,GAAG,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACjE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAErE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,4BAA4B,OAAO,eAAe,YAAY,CAAC,MAAM,YAAY,SAAS,CAAC,MAAM,SAAS,cAAc,CAAC,MAAM,WAAW,CAAC,CAAC;IAExJ,6CAA6C;IAC7C,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtD,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC/G,MAAM,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAC1I,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACvE,MAAM,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QACpG,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YAC9D,MAAM,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAED,+BAA+B;IAC/B,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACjD,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAChE,CAAC;IAED,6BAA6B;IAC7B,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,GAAG,KAAK,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC;QAC9E,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACjG,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,MAAM,MAAM,CAAC,OAAO,MAAM,MAAM,CAAC,QAAQ,MAAM,CAAC,CAAC;QAC9E,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;QAC3F,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,mBAAmB,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;QACzF,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,kBAAkB,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,QAAQ,GAAG,IAAI,CAAC;AAEpB,kBAAkB;AAClB,OAAO,EAAE,CAAC;AAEV,mBAAmB;AACnB,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;AAEhE,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,39 @@ export interface Snapshot {
10
10
  raid: RaidInfo[];
11
11
  ipmi: IpmiInfo;
12
12
  os_alerts: OsAlerts;
13
+ security?: SecurityData;
14
+ }
15
+ export interface SecurityData {
16
+ ssh: {
17
+ permitRootLogin: string;
18
+ passwordAuthentication: string;
19
+ rootPasswordExposed: boolean;
20
+ } | null;
21
+ firewall: {
22
+ active: boolean;
23
+ source: string;
24
+ details: string;
25
+ };
26
+ pending_updates: {
27
+ distro: string;
28
+ pendingCount: number;
29
+ available: boolean;
30
+ } | null;
31
+ kernel_vulns: Array<{
32
+ name: string;
33
+ status: string;
34
+ mitigated: boolean;
35
+ }>;
36
+ kernel_reboot: {
37
+ running: string;
38
+ installed: string;
39
+ needsReboot: boolean;
40
+ } | null;
41
+ auto_updates: {
42
+ configured: boolean;
43
+ mechanism: string;
44
+ details: string;
45
+ };
13
46
  }
14
47
  export interface SystemInfo {
15
48
  hostname: string;
@@ -18,6 +51,15 @@ export interface SystemInfo {
18
51
  kernel: string;
19
52
  uptime_seconds: number;
20
53
  }
54
+ export interface CpuCoreInfo {
55
+ core: number;
56
+ user_percent: number;
57
+ system_percent: number;
58
+ iowait_percent: number;
59
+ idle_percent: number;
60
+ irq_percent: number;
61
+ softirq_percent: number;
62
+ }
21
63
  export interface CpuInfo {
22
64
  user_percent: number;
23
65
  system_percent: number;
@@ -26,6 +68,7 @@ export interface CpuInfo {
26
68
  load_1m: number;
27
69
  load_5m: number;
28
70
  load_15m: number;
71
+ cores?: CpuCoreInfo[];
29
72
  }
30
73
  export interface MemoryInfo {
31
74
  total_mb: number;
@@ -41,6 +84,11 @@ export interface DiskInfo {
41
84
  used_gb: number;
42
85
  available_gb: number;
43
86
  percent_used: number;
87
+ fstype?: string;
88
+ options?: string;
89
+ inodes_total?: number;
90
+ inodes_used?: number;
91
+ inodes_free?: number;
44
92
  io_read_mb_s?: number;
45
93
  io_write_mb_s?: number;
46
94
  latency_p99_ms?: number;
@@ -73,6 +121,20 @@ export interface RaidInfo {
73
121
  disks: string[];
74
122
  failed_disks: string[];
75
123
  }
124
+ export interface SelEvent {
125
+ id: number;
126
+ timestamp: string;
127
+ sensor: string;
128
+ sensor_type: string;
129
+ event: string;
130
+ direction: string;
131
+ severity: string;
132
+ }
133
+ export interface FanStatus {
134
+ name: string;
135
+ rpm: number;
136
+ status: string;
137
+ }
76
138
  export interface IpmiInfo {
77
139
  available: boolean;
78
140
  sensors: Array<{
@@ -87,6 +149,8 @@ export interface IpmiInfo {
87
149
  uncorrectable: number;
88
150
  };
89
151
  sel_entries_count: number;
152
+ sel_events_recent: SelEvent[];
153
+ fans: FanStatus[];
90
154
  }
91
155
  export interface OsAlerts {
92
156
  oom_kills_recent: number;
@@ -0,0 +1,7 @@
1
+ export declare function getCurrentVersion(): string;
2
+ export declare function checkForUpdates(forgeUrl?: string): Promise<void>;
3
+ export declare function getUpdateStatus(): {
4
+ updateAvailable: boolean;
5
+ latest: string;
6
+ changelog: string;
7
+ } | null;
@@ -0,0 +1,39 @@
1
+ const CURRENT_VERSION = "0.1.0";
2
+ let lastCheckTime = 0;
3
+ let lastResult = null;
4
+ const CHECK_INTERVAL = 6 * 60 * 60 * 1000; // check every 6 hours
5
+ export function getCurrentVersion() {
6
+ return CURRENT_VERSION;
7
+ }
8
+ export async function checkForUpdates(forgeUrl) {
9
+ const now = Date.now();
10
+ if (now - lastCheckTime < CHECK_INTERVAL)
11
+ return;
12
+ lastCheckTime = now;
13
+ const url = forgeUrl || "https://forge.glassmkr.com";
14
+ try {
15
+ const res = await fetch(`${url}/api/v1/version`, { signal: AbortSignal.timeout(5000) });
16
+ if (!res.ok)
17
+ return;
18
+ const data = await res.json();
19
+ const latest = data.crucible?.latest;
20
+ if (!latest)
21
+ return;
22
+ if (latest !== CURRENT_VERSION) {
23
+ console.log(`[update] New Crucible version available: ${latest} (current: ${CURRENT_VERSION})`);
24
+ console.log(`[update] Changelog: ${data.crucible?.changelog_url || "https://github.com/glassmkr/crucible/releases"}`);
25
+ console.log(`[update] Run: npm update -g @glassmkr/crucible && sudo systemctl restart glassmkr-collector`);
26
+ lastResult = { updateAvailable: true, latest, changelog: data.crucible?.changelog_url || "" };
27
+ }
28
+ else {
29
+ lastResult = { updateAvailable: false, latest, changelog: "" };
30
+ }
31
+ }
32
+ catch {
33
+ // Version check is non-critical, fail silently
34
+ }
35
+ }
36
+ export function getUpdateStatus() {
37
+ return lastResult;
38
+ }
39
+ //# sourceMappingURL=version-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-check.js","sourceRoot":"","sources":["../../src/lib/version-check.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG,OAAO,CAAC;AAChC,IAAI,aAAa,GAAG,CAAC,CAAC;AACtB,IAAI,UAAU,GAA2E,IAAI,CAAC;AAC9F,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,sBAAsB;AAEjE,MAAM,UAAU,iBAAiB;IAC/B,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAiB;IACrD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,GAAG,GAAG,aAAa,GAAG,cAAc;QAAE,OAAO;IACjD,aAAa,GAAG,GAAG,CAAC;IAEpB,MAAM,GAAG,GAAG,QAAQ,IAAI,4BAA4B,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,iBAAiB,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO;QACpB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAwF,CAAC;QACpH,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,4CAA4C,MAAM,cAAc,eAAe,GAAG,CAAC,CAAC;YAChG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,CAAC,QAAQ,EAAE,aAAa,IAAI,+CAA+C,EAAE,CAAC,CAAC;YACtH,OAAO,CAAC,GAAG,CAAC,6FAA6F,CAAC,CAAC;YAC3G,UAAU,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,aAAa,IAAI,EAAE,EAAE,CAAC;QAChG,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QACjE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Snapshot } from "./lib/types.js";
2
+ export declare function updateMetrics(snapshot: Snapshot): void;
3
+ export declare function startMetricsServer(port: number): void;
@@ -0,0 +1,113 @@
1
+ import { createServer } from "http";
2
+ let latestSnapshot = null;
3
+ export function updateMetrics(snapshot) {
4
+ latestSnapshot = snapshot;
5
+ }
6
+ export function startMetricsServer(port) {
7
+ const server = createServer((req, res) => {
8
+ if (req.url === "/metrics" && req.method === "GET") {
9
+ if (!latestSnapshot) {
10
+ res.writeHead(503);
11
+ res.end("# No data collected yet\n");
12
+ return;
13
+ }
14
+ res.writeHead(200, { "Content-Type": "text/plain; version=0.0.4" });
15
+ res.end(formatPrometheus(latestSnapshot));
16
+ }
17
+ else if (req.url === "/health") {
18
+ res.writeHead(200);
19
+ res.end("ok\n");
20
+ }
21
+ else {
22
+ res.writeHead(404);
23
+ res.end("Not found\n");
24
+ }
25
+ });
26
+ server.listen(port, "0.0.0.0", () => {
27
+ console.log(`[metrics] Prometheus endpoint listening on :${port}/metrics`);
28
+ });
29
+ }
30
+ function formatPrometheus(snap) {
31
+ const lines = [];
32
+ // CPU
33
+ lines.push("# HELP glassmkr_cpu_user_percent CPU user utilization");
34
+ lines.push("# TYPE glassmkr_cpu_user_percent gauge");
35
+ lines.push(`glassmkr_cpu_user_percent ${snap.cpu.user_percent}`);
36
+ lines.push(`glassmkr_cpu_system_percent ${snap.cpu.system_percent}`);
37
+ lines.push(`glassmkr_cpu_iowait_percent ${snap.cpu.iowait_percent}`);
38
+ lines.push(`glassmkr_cpu_idle_percent ${snap.cpu.idle_percent}`);
39
+ lines.push(`glassmkr_load_1m ${snap.cpu.load_1m}`);
40
+ lines.push(`glassmkr_load_5m ${snap.cpu.load_5m}`);
41
+ lines.push(`glassmkr_load_15m ${snap.cpu.load_15m}`);
42
+ // Memory
43
+ lines.push("# HELP glassmkr_memory_used_mb Memory used in MB");
44
+ lines.push("# TYPE glassmkr_memory_used_mb gauge");
45
+ lines.push(`glassmkr_memory_used_mb ${snap.memory.used_mb}`);
46
+ lines.push(`glassmkr_memory_total_mb ${snap.memory.total_mb}`);
47
+ lines.push(`glassmkr_memory_available_mb ${snap.memory.available_mb}`);
48
+ lines.push(`glassmkr_swap_used_mb ${snap.memory.swap_used_mb}`);
49
+ // Disks
50
+ lines.push("# HELP glassmkr_disk_used_percent Disk usage percentage");
51
+ lines.push("# TYPE glassmkr_disk_used_percent gauge");
52
+ for (const disk of snap.disks) {
53
+ const labels = `mount="${disk.mount}",device="${disk.device}"`;
54
+ lines.push(`glassmkr_disk_used_percent{${labels}} ${disk.percent_used}`);
55
+ lines.push(`glassmkr_disk_total_gb{${labels}} ${disk.total_gb}`);
56
+ lines.push(`glassmkr_disk_used_gb{${labels}} ${disk.used_gb}`);
57
+ }
58
+ // Network
59
+ lines.push("# HELP glassmkr_net_rx_bytes_sec Network receive bytes per second");
60
+ lines.push("# TYPE glassmkr_net_rx_bytes_sec gauge");
61
+ for (const iface of snap.network) {
62
+ const labels = `interface="${iface.interface}"`;
63
+ lines.push(`glassmkr_net_rx_bytes_sec{${labels}} ${iface.rx_bytes_sec}`);
64
+ lines.push(`glassmkr_net_tx_bytes_sec{${labels}} ${iface.tx_bytes_sec}`);
65
+ lines.push(`glassmkr_net_rx_errors{${labels}} ${iface.rx_errors}`);
66
+ lines.push(`glassmkr_net_tx_errors{${labels}} ${iface.tx_errors}`);
67
+ lines.push(`glassmkr_net_speed_mbps{${labels}} ${iface.speed_mbps}`);
68
+ }
69
+ // SMART
70
+ for (const drive of snap.smart) {
71
+ const labels = `device="${drive.device}",model="${drive.model}"`;
72
+ if (drive.temperature_c != null)
73
+ lines.push(`glassmkr_smart_temperature_c{${labels}} ${drive.temperature_c}`);
74
+ if (drive.percentage_used != null)
75
+ lines.push(`glassmkr_smart_percentage_used{${labels}} ${drive.percentage_used}`);
76
+ if (drive.reallocated_sectors != null)
77
+ lines.push(`glassmkr_smart_reallocated_sectors{${labels}} ${drive.reallocated_sectors}`);
78
+ }
79
+ // IPMI
80
+ if (snap.ipmi?.available) {
81
+ for (const sensor of snap.ipmi.sensors) {
82
+ if (typeof sensor.value === "number") {
83
+ const sensorName = sensor.name.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
84
+ lines.push(`glassmkr_ipmi_sensor{sensor="${sensor.name}",unit="${sensor.unit}"} ${sensor.value}`);
85
+ }
86
+ }
87
+ lines.push(`glassmkr_ipmi_ecc_correctable ${snap.ipmi.ecc_errors.correctable}`);
88
+ lines.push(`glassmkr_ipmi_ecc_uncorrectable ${snap.ipmi.ecc_errors.uncorrectable}`);
89
+ // Fans
90
+ if (snap.ipmi.fans) {
91
+ for (const fan of snap.ipmi.fans) {
92
+ lines.push(`glassmkr_ipmi_fan_rpm{fan="${fan.name}",status="${fan.status}"} ${fan.rpm}`);
93
+ }
94
+ }
95
+ }
96
+ // OS alerts
97
+ lines.push(`glassmkr_oom_kills_recent ${snap.os_alerts.oom_kills_recent}`);
98
+ lines.push(`glassmkr_zombie_processes ${snap.os_alerts.zombie_processes}`);
99
+ // Security
100
+ if (snap.security) {
101
+ lines.push(`glassmkr_ssh_root_password_exposed ${snap.security.ssh?.rootPasswordExposed ? 1 : 0}`);
102
+ lines.push(`glassmkr_firewall_active ${snap.security.firewall.active ? 1 : 0}`);
103
+ if (snap.security.pending_updates?.available) {
104
+ lines.push(`glassmkr_pending_security_updates ${snap.security.pending_updates.pendingCount}`);
105
+ }
106
+ const unmitigated = snap.security.kernel_vulns.filter(v => !v.mitigated).length;
107
+ lines.push(`glassmkr_kernel_vulns_unmitigated ${unmitigated}`);
108
+ lines.push(`glassmkr_kernel_needs_reboot ${snap.security.kernel_reboot?.needsReboot ? 1 : 0}`);
109
+ lines.push(`glassmkr_auto_updates_configured ${snap.security.auto_updates.configured ? 1 : 0}`);
110
+ }
111
+ return lines.join("\n") + "\n";
112
+ }
113
+ //# sourceMappingURL=metrics-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-server.js","sourceRoot":"","sources":["../src/metrics-server.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,34 @@
1
+ const PRIORITY_MAP = {
2
+ raid_degraded: "P1", smart_failing: "P1", ecc_errors: "P1", psu_redundancy_loss: "P1", ipmi_fan_failure: "P1",
3
+ oom_kills: "P2", ram_high: "P2", disk_space_high: "P2", ipmi_sel_critical: "P2", disk_io_errors: "P2", zfs_pool_unhealthy: "P2",
4
+ cpu_iowait_high: "P3", nvme_wear_high: "P3", disk_latency_high: "P3", cpu_temperature_high: "P3",
5
+ ssh_root_password: "P3", pending_security_updates: "P3", kernel_vulnerabilities: "P3", zfs_scrub_errors: "P3",
6
+ swap_active: "P4", no_firewall: "P4", kernel_needs_reboot: "P4", unattended_upgrades_disabled: "P4",
7
+ interface_errors: "P4", link_speed_mismatch: "P4", interface_saturation: "P4",
8
+ };
9
+ const PRIORITY_LABELS = {
10
+ P1: "\u{1F534} P1 Urgent", P2: "\u{1F7E0} P2 High", P3: "\u{1F7E1} P3 Medium", P4: "\u{1F535} P4 Low",
11
+ };
12
+ function getPriority(alertType) {
13
+ return PRIORITY_MAP[alertType] || "P3";
14
+ }
1
15
  export async function sendTelegram(botToken, chatId, newAlerts, resolvedAlerts, serverName) {
2
16
  const parts = [];
3
17
  if (newAlerts.length > 0) {
4
- const criticals = newAlerts.filter((a) => a.severity === "critical");
5
- const warnings = newAlerts.filter((a) => a.severity === "warning");
6
- if (criticals.length > 0) {
7
- parts.push(`\u{1F534} <b>${criticals.length} CRITICAL</b> on <b>${serverName}</b>:\n`);
8
- for (const a of criticals)
9
- parts.push(` \u2022 <b>${a.title}</b>\n ${a.recommendation}\n`);
18
+ // Group by priority
19
+ const byPriority = {};
20
+ for (const a of newAlerts) {
21
+ const p = getPriority(a.type);
22
+ if (!byPriority[p])
23
+ byPriority[p] = [];
24
+ byPriority[p].push(a);
10
25
  }
11
- if (warnings.length > 0) {
12
- parts.push(`\u{1F7E1} <b>${warnings.length} WARNING</b> on <b>${serverName}</b>:\n`);
13
- for (const a of warnings)
26
+ for (const p of ["P1", "P2", "P3", "P4"]) {
27
+ const alerts = byPriority[p];
28
+ if (!alerts?.length)
29
+ continue;
30
+ parts.push(`${PRIORITY_LABELS[p]} on <b>${serverName}</b>:\n`);
31
+ for (const a of alerts)
14
32
  parts.push(` \u2022 <b>${a.title}</b>\n ${a.recommendation}\n`);
15
33
  }
16
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/notify/telegram.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,MAAc,EACd,SAAwB,EACxB,cAA6B,EAC7B,UAAkB;IAElB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;QACrE,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;QAEnE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,gBAAgB,SAAS,CAAC,MAAM,uBAAuB,UAAU,SAAS,CAAC,CAAC;YACvF,KAAK,MAAM,CAAC,IAAI,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC;QAC/F,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,gBAAgB,QAAQ,CAAC,MAAM,sBAAsB,UAAU,SAAS,CAAC,CAAC;YACrF,KAAK,MAAM,CAAC,IAAI,QAAQ;gBAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAED,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,aAAa,cAAc,CAAC,MAAM,uBAAuB,UAAU,SAAS,CAAC,CAAC;QACzF,KAAK,MAAM,CAAC,IAAI,cAAc;YAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,+BAA+B,QAAQ,cAAc,EAAE;YAC7E,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,wBAAwB,EAAE,IAAI,EAAE,CAAC;YACrH,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;SACnC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,EAAE,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/notify/telegram.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,3 @@
1
1
  import type { Snapshot } from "../lib/types.js";
2
+ export declare function initForgeAgent(tlsPin?: string): void;
2
3
  export declare function pushToForge(url: string, apiKey: string, snapshot: Snapshot): Promise<boolean>;
@@ -1,11 +1,41 @@
1
+ import https from "https";
2
+ import tls from "tls";
3
+ import crypto from "crypto";
4
+ let agent;
5
+ export function initForgeAgent(tlsPin) {
6
+ if (!tlsPin) {
7
+ agent = undefined; // Use default (Node built-in fetch)
8
+ return;
9
+ }
10
+ agent = new https.Agent({
11
+ rejectUnauthorized: true,
12
+ checkServerIdentity: (hostname, cert) => {
13
+ const err = tls.checkServerIdentity(hostname, cert);
14
+ if (err)
15
+ return err;
16
+ const pubkey = cert.pubkey;
17
+ if (!pubkey)
18
+ return new Error("Certificate has no public key");
19
+ const hash = crypto.createHash("sha256").update(pubkey).digest("base64");
20
+ if (hash !== tlsPin) {
21
+ return new Error(`TLS pin mismatch for ${hostname}. ` +
22
+ `Expected: ${tlsPin}, Got: ${hash}. ` +
23
+ `If the server certificate was rotated with a new key, update tls_pin in collector.yaml.`);
24
+ }
25
+ return undefined;
26
+ },
27
+ });
28
+ }
1
29
  export async function pushToForge(url, apiKey, snapshot) {
30
+ // If TLS pinning is enabled, use https.request (fetch doesn't support custom agents)
31
+ if (agent) {
32
+ return pushWithAgent(url, apiKey, snapshot);
33
+ }
34
+ // Default: use fetch (no pinning)
2
35
  try {
3
36
  const response = await fetch(`${url}/api/v1/ingest`, {
4
37
  method: "POST",
5
- headers: {
6
- Authorization: `Bearer ${apiKey}`,
7
- "Content-Type": "application/json",
8
- },
38
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
9
39
  body: JSON.stringify(snapshot),
10
40
  signal: AbortSignal.timeout(10000),
11
41
  });
@@ -23,4 +53,50 @@ export async function pushToForge(url, apiKey, snapshot) {
23
53
  return false;
24
54
  }
25
55
  }
56
+ function pushWithAgent(url, apiKey, snapshot) {
57
+ return new Promise((resolve) => {
58
+ const parsed = new URL(`${url}/api/v1/ingest`);
59
+ const body = JSON.stringify(snapshot);
60
+ const req = https.request({
61
+ hostname: parsed.hostname,
62
+ port: parsed.port ? parseInt(parsed.port) : 443,
63
+ path: parsed.pathname,
64
+ method: "POST",
65
+ agent,
66
+ headers: {
67
+ Authorization: `Bearer ${apiKey}`,
68
+ "Content-Type": "application/json",
69
+ "Content-Length": Buffer.byteLength(body),
70
+ },
71
+ timeout: 10000,
72
+ }, (res) => {
73
+ let data = "";
74
+ res.on("data", (chunk) => data += chunk);
75
+ res.on("end", () => {
76
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
77
+ try {
78
+ const parsed = JSON.parse(data);
79
+ console.log(`[forge] Push successful (pinned). Active alerts: ${parsed.active_alerts ?? 0}`);
80
+ }
81
+ catch { /* ignore parse errors */ }
82
+ resolve(true);
83
+ }
84
+ else {
85
+ console.error(`[forge] Push failed (pinned): ${res.statusCode}`);
86
+ resolve(false);
87
+ }
88
+ });
89
+ });
90
+ req.on("error", (err) => {
91
+ console.error(`[forge] Push failed (pinned): ${err.message}`);
92
+ resolve(false);
93
+ });
94
+ req.on("timeout", () => {
95
+ req.destroy(new Error("Request timed out"));
96
+ resolve(false);
97
+ });
98
+ req.write(body);
99
+ req.end();
100
+ });
101
+ }
26
102
  //# sourceMappingURL=forge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"forge.js","sourceRoot":"","sources":["../../src/push/forge.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,MAAc,EAAE,QAAkB;IAC/E,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,gBAAgB,EAAE;YACnD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,MAAM,EAAE;gBACjC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;YAC9B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;SACnC,CAAC,CAAC;QACH,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAqD,CAAC;YACtF,OAAO,CAAC,GAAG,CAAC,2CAA2C,IAAI,CAAC,aAAa,IAAI,CAAC,EAAE,CAAC,CAAC;QACpF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,QAAQ,CAAC,EAAE,CAAC;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC5D,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"forge.js","sourceRoot":"","sources":["../../src/push/forge.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.1.0",
3
+ "version": "0.3.1",
4
4
  "description": "Lightweight bare metal server monitoring. IPMI, SMART, OS, network. Opinionated alerts.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,29 @@
1
+ #!/bin/bash
2
+ # Sign a Crucible release
3
+ # Usage: ./scripts/sign-release.sh <version>
4
+
5
+ VERSION=$1
6
+ DIST_DIR="dist"
7
+
8
+ if [ -z "$VERSION" ]; then
9
+ echo "Usage: ./scripts/sign-release.sh <version>"
10
+ echo "Example: ./scripts/sign-release.sh v0.2.0"
11
+ exit 1
12
+ fi
13
+
14
+ echo "Signing Crucible $VERSION"
15
+
16
+ # Generate checksums
17
+ cd "$DIST_DIR" || exit 1
18
+ sha256sum *.tar.gz *.deb 2>/dev/null > SHA256SUMS || sha256sum *.js > SHA256SUMS
19
+
20
+ # Sign the checksums file
21
+ gpg --armor --detach-sign --local-user security@glassmkr.com SHA256SUMS
22
+
23
+ echo ""
24
+ echo "Release artifacts:"
25
+ ls -la SHA256SUMS SHA256SUMS.asc
26
+ echo ""
27
+ echo "Verify with:"
28
+ echo " gpg --verify SHA256SUMS.asc SHA256SUMS"
29
+ echo " sha256sum -c SHA256SUMS"
@@ -181,4 +181,103 @@ export const allRules: AlertRule[] = [
181
181
  evidence: { failed: failed.map(p => ({ name: p.name, status: p.status })) },
182
182
  recommendation: "Replace failed PSU. Check power connections." }];
183
183
  }},
184
+ // 19. IPMI SEL critical events
185
+ { type: "ipmi_sel_critical", evaluate(snap) {
186
+ if (!snap.ipmi?.available || !snap.ipmi.sel_events_recent?.length) return [];
187
+ const critical = snap.ipmi.sel_events_recent.filter(e => e.severity === "critical" && e.direction === "Asserted");
188
+ if (critical.length === 0) return [];
189
+ const byType: Record<string, typeof critical> = {};
190
+ for (const e of critical) { if (!byType[e.sensor_type]) byType[e.sensor_type] = []; byType[e.sensor_type].push(e); }
191
+ const details = Object.entries(byType).map(([t, evts]) => `${t}: ${evts.map(e => `${e.sensor}: ${e.event}`).join(", ")}`).join("; ");
192
+ const recs: string[] = [];
193
+ if (byType.memory) recs.push("Memory errors: identify slot with `ipmitool sel elist | grep -i memory`. Schedule DIMM replacement.");
194
+ if (byType.power) recs.push("PSU event: check physical PSU and connections. Verify redundancy: `ipmitool chassis status`.");
195
+ if (byType.watchdog) recs.push("Watchdog reset: OS or BMC became unresponsive. Check dmesg for root cause.");
196
+ if (byType.processor) recs.push("CPU event: check for thermal throttling or MCE. Run `dmesg | grep -i mce`.");
197
+ if (recs.length === 0) recs.push("Review full SEL: `ipmitool sel elist`.");
198
+ return [{ type: "ipmi_sel_critical", severity: "critical",
199
+ title: `IPMI: ${critical.length} critical hardware event(s)`,
200
+ message: `BMC System Event Log: ${critical.length} critical event(s). ${details}`,
201
+ evidence: { critical_events: critical, sensor_types: Object.keys(byType) },
202
+ recommendation: recs.join(" ") }];
203
+ }},
204
+ // 20. Fan failure
205
+ { type: "ipmi_fan_failure", evaluate(snap) {
206
+ if (!snap.ipmi?.available || !snap.ipmi.fans?.length) return [];
207
+ const failed = snap.ipmi.fans.filter(f => f.status === "critical" || (f.rpm === 0 && f.status !== "absent"));
208
+ if (failed.length === 0) return [];
209
+ const total = snap.ipmi.fans.filter(f => f.status !== "absent").length;
210
+ const names = failed.map(f => `${f.name} (${f.rpm} RPM)`).join(", ");
211
+ return [{ type: "ipmi_fan_failure", severity: "critical",
212
+ title: `Fan failure: ${failed.length} of ${total} fans`,
213
+ message: `${failed.length} fan(s) stopped or critically slow: ${names}. Reduced cooling capacity.`,
214
+ evidence: { failed_fans: failed, total_fans: total, all_fans: snap.ipmi.fans.filter(f => f.status !== "absent") },
215
+ recommendation: "Check physical fans. Monitor temps: `ipmitool sdr type Temperature`. Replace failed fan module." }];
216
+ }},
217
+ // === Security (6) ===
218
+ // 21. SSH root password login
219
+ { type: "ssh_root_password", evaluate(snap) {
220
+ if (!snap.security?.ssh?.rootPasswordExposed) return [];
221
+ return [{ type: "ssh_root_password", severity: "warning",
222
+ title: "SSH root login with password enabled",
223
+ message: `PermitRootLogin is "${snap.security.ssh.permitRootLogin}" and PasswordAuthentication is "${snap.security.ssh.passwordAuthentication}". Root can be brute-forced over SSH.`,
224
+ evidence: { permitRootLogin: snap.security.ssh.permitRootLogin, passwordAuthentication: snap.security.ssh.passwordAuthentication },
225
+ recommendation: 'Set "PermitRootLogin prohibit-password" in /etc/ssh/sshd_config and restart sshd. Key-based root login still works.' }];
226
+ }},
227
+ // 22. No firewall
228
+ { type: "no_firewall", evaluate(snap) {
229
+ if (!snap.security || snap.security.firewall.active) return [];
230
+ return [{ type: "no_firewall", severity: "warning" as const,
231
+ title: "No firewall active",
232
+ message: "No active firewall rules detected (checked UFW, firewalld, nftables, iptables). All ports are exposed unless protected by network-level ACLs.",
233
+ evidence: { source: snap.security.firewall.source },
234
+ recommendation: 'Enable a firewall: "sudo ufw enable" (Debian/Ubuntu) or "sudo systemctl start firewalld" (RHEL/Rocky).' }];
235
+ }},
236
+ // 23. Pending security updates
237
+ { type: "pending_security_updates", evaluate(snap, t) {
238
+ if (!snap.security?.pending_updates?.available) return [];
239
+ const maxPending = 10;
240
+ if (snap.security.pending_updates.pendingCount <= maxPending) return [];
241
+ const d = snap.security.pending_updates;
242
+ return [{ type: "pending_security_updates", severity: "warning",
243
+ title: `${d.pendingCount} security updates pending`,
244
+ message: `${d.pendingCount} security updates pending on this ${d.distro} server.`,
245
+ evidence: { pendingCount: d.pendingCount, distro: d.distro },
246
+ recommendation: d.distro === "ubuntu" || d.distro === "debian" ? 'Apply with: "sudo apt-get upgrade"' : 'Apply with: "sudo dnf update --security"' }];
247
+ }},
248
+ // 24. Kernel vulnerabilities
249
+ { type: "kernel_vulnerabilities", evaluate(snap) {
250
+ if (!snap.security?.kernel_vulns?.length) return [];
251
+ const unmitigated = snap.security.kernel_vulns.filter(v => !v.mitigated);
252
+ if (unmitigated.length === 0) return [];
253
+ const details = unmitigated.map(v => `${v.name}: ${v.status}`).join("; ");
254
+ return [{ type: "kernel_vulnerabilities", severity: "warning",
255
+ title: `${unmitigated.length} CPU vulnerability mitigations missing`,
256
+ message: `Unmitigated: ${details}. Update the kernel and CPU microcode to apply mitigations.`,
257
+ evidence: { unmitigated, total: snap.security.kernel_vulns.length },
258
+ recommendation: 'Check: "grep . /sys/devices/system/cpu/vulnerabilities/*". Update kernel and microcode packages.' }];
259
+ }},
260
+ // 25. Kernel needs reboot
261
+ { type: "kernel_needs_reboot", evaluate(snap) {
262
+ if (!snap.security?.kernel_reboot?.needsReboot) return [];
263
+ const k = snap.security.kernel_reboot;
264
+ return [{ type: "kernel_needs_reboot", severity: "warning" as const,
265
+ title: "Reboot required for kernel update",
266
+ message: `Running kernel: ${k.running}. Installed kernel: ${k.installed}. A reboot is needed to apply the newer kernel.`,
267
+ evidence: { running: k.running, installed: k.installed },
268
+ recommendation: "Schedule a reboot to apply the newer kernel. Security patches may not be active until then." }];
269
+ }},
270
+ // 26. Unattended upgrades disabled
271
+ { type: "unattended_upgrades_disabled", evaluate(snap) {
272
+ if (!snap.security || snap.security.auto_updates.configured) return [];
273
+ const a = snap.security.auto_updates;
274
+ const hint = a.mechanism === "unattended-upgrades" ? 'Enable: "sudo dpkg-reconfigure -plow unattended-upgrades"'
275
+ : a.mechanism === "dnf-automatic" ? 'Enable: "sudo systemctl enable --now dnf-automatic-install.timer"'
276
+ : 'Install: "sudo apt install unattended-upgrades" (Debian/Ubuntu) or "sudo dnf install dnf-automatic" (RHEL/Rocky)';
277
+ return [{ type: "unattended_upgrades_disabled", severity: "warning" as const,
278
+ title: "Automatic security updates not configured",
279
+ message: `${a.details}. Without automatic updates, security patches must be applied manually.`,
280
+ evidence: { mechanism: a.mechanism, details: a.details },
281
+ recommendation: hint }];
282
+ }},
184
283
  ];