@sonde/agent 0.0.0

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 (149) hide show
  1. package/dist/cli/packs.d.ts +23 -0
  2. package/dist/cli/packs.d.ts.map +1 -0
  3. package/dist/cli/packs.js +172 -0
  4. package/dist/cli/packs.js.map +1 -0
  5. package/dist/cli/packs.test.d.ts +2 -0
  6. package/dist/cli/packs.test.d.ts.map +1 -0
  7. package/dist/cli/packs.test.js +171 -0
  8. package/dist/cli/packs.test.js.map +1 -0
  9. package/dist/config.d.ts +18 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +38 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/index.d.ts +13 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +191 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/runtime/attestation.d.ts +9 -0
  18. package/dist/runtime/attestation.d.ts.map +1 -0
  19. package/dist/runtime/attestation.js +32 -0
  20. package/dist/runtime/attestation.js.map +1 -0
  21. package/dist/runtime/attestation.test.d.ts +2 -0
  22. package/dist/runtime/attestation.test.d.ts.map +1 -0
  23. package/dist/runtime/attestation.test.js +59 -0
  24. package/dist/runtime/attestation.test.js.map +1 -0
  25. package/dist/runtime/audit.d.ts +19 -0
  26. package/dist/runtime/audit.d.ts.map +1 -0
  27. package/dist/runtime/audit.js +52 -0
  28. package/dist/runtime/audit.js.map +1 -0
  29. package/dist/runtime/audit.test.d.ts +2 -0
  30. package/dist/runtime/audit.test.d.ts.map +1 -0
  31. package/dist/runtime/audit.test.js +53 -0
  32. package/dist/runtime/audit.test.js.map +1 -0
  33. package/dist/runtime/connection.d.ts +55 -0
  34. package/dist/runtime/connection.d.ts.map +1 -0
  35. package/dist/runtime/connection.js +325 -0
  36. package/dist/runtime/connection.js.map +1 -0
  37. package/dist/runtime/connection.test.d.ts +2 -0
  38. package/dist/runtime/connection.test.d.ts.map +1 -0
  39. package/dist/runtime/connection.test.js +221 -0
  40. package/dist/runtime/connection.test.js.map +1 -0
  41. package/dist/runtime/executor.d.ts +21 -0
  42. package/dist/runtime/executor.d.ts.map +1 -0
  43. package/dist/runtime/executor.js +89 -0
  44. package/dist/runtime/executor.js.map +1 -0
  45. package/dist/runtime/executor.test.d.ts +2 -0
  46. package/dist/runtime/executor.test.d.ts.map +1 -0
  47. package/dist/runtime/executor.test.js +88 -0
  48. package/dist/runtime/executor.test.js.map +1 -0
  49. package/dist/runtime/privilege.d.ts +9 -0
  50. package/dist/runtime/privilege.d.ts.map +1 -0
  51. package/dist/runtime/privilege.js +35 -0
  52. package/dist/runtime/privilege.js.map +1 -0
  53. package/dist/runtime/privilege.test.d.ts +2 -0
  54. package/dist/runtime/privilege.test.d.ts.map +1 -0
  55. package/dist/runtime/privilege.test.js +22 -0
  56. package/dist/runtime/privilege.test.js.map +1 -0
  57. package/dist/runtime/scrubber.d.ts +17 -0
  58. package/dist/runtime/scrubber.d.ts.map +1 -0
  59. package/dist/runtime/scrubber.js +84 -0
  60. package/dist/runtime/scrubber.js.map +1 -0
  61. package/dist/runtime/scrubber.test.d.ts +2 -0
  62. package/dist/runtime/scrubber.test.d.ts.map +1 -0
  63. package/dist/runtime/scrubber.test.js +72 -0
  64. package/dist/runtime/scrubber.test.js.map +1 -0
  65. package/dist/system/scanner.d.ts +32 -0
  66. package/dist/system/scanner.d.ts.map +1 -0
  67. package/dist/system/scanner.js +90 -0
  68. package/dist/system/scanner.js.map +1 -0
  69. package/dist/system/scanner.test.d.ts +2 -0
  70. package/dist/system/scanner.test.d.ts.map +1 -0
  71. package/dist/system/scanner.test.js +121 -0
  72. package/dist/system/scanner.test.js.map +1 -0
  73. package/dist/tui/installer/InstallerApp.d.ts +11 -0
  74. package/dist/tui/installer/InstallerApp.d.ts.map +1 -0
  75. package/dist/tui/installer/InstallerApp.js +32 -0
  76. package/dist/tui/installer/InstallerApp.js.map +1 -0
  77. package/dist/tui/installer/StepComplete.d.ts +9 -0
  78. package/dist/tui/installer/StepComplete.d.ts.map +1 -0
  79. package/dist/tui/installer/StepComplete.js +46 -0
  80. package/dist/tui/installer/StepComplete.js.map +1 -0
  81. package/dist/tui/installer/StepHub.d.ts +8 -0
  82. package/dist/tui/installer/StepHub.d.ts.map +1 -0
  83. package/dist/tui/installer/StepHub.js +65 -0
  84. package/dist/tui/installer/StepHub.js.map +1 -0
  85. package/dist/tui/installer/StepPacks.d.ts +9 -0
  86. package/dist/tui/installer/StepPacks.d.ts.map +1 -0
  87. package/dist/tui/installer/StepPacks.js +35 -0
  88. package/dist/tui/installer/StepPacks.js.map +1 -0
  89. package/dist/tui/installer/StepPermissions.d.ts +9 -0
  90. package/dist/tui/installer/StepPermissions.d.ts.map +1 -0
  91. package/dist/tui/installer/StepPermissions.js +39 -0
  92. package/dist/tui/installer/StepPermissions.js.map +1 -0
  93. package/dist/tui/installer/StepScan.d.ts +7 -0
  94. package/dist/tui/installer/StepScan.d.ts.map +1 -0
  95. package/dist/tui/installer/StepScan.js +38 -0
  96. package/dist/tui/installer/StepScan.js.map +1 -0
  97. package/dist/tui/manager/ActivityLog.d.ts +7 -0
  98. package/dist/tui/manager/ActivityLog.d.ts.map +1 -0
  99. package/dist/tui/manager/ActivityLog.js +25 -0
  100. package/dist/tui/manager/ActivityLog.js.map +1 -0
  101. package/dist/tui/manager/AuditView.d.ts +7 -0
  102. package/dist/tui/manager/AuditView.d.ts.map +1 -0
  103. package/dist/tui/manager/AuditView.js +32 -0
  104. package/dist/tui/manager/AuditView.js.map +1 -0
  105. package/dist/tui/manager/ManagerApp.d.ts +20 -0
  106. package/dist/tui/manager/ManagerApp.d.ts.map +1 -0
  107. package/dist/tui/manager/ManagerApp.js +79 -0
  108. package/dist/tui/manager/ManagerApp.js.map +1 -0
  109. package/dist/tui/manager/PackManager.d.ts +7 -0
  110. package/dist/tui/manager/PackManager.d.ts.map +1 -0
  111. package/dist/tui/manager/PackManager.js +22 -0
  112. package/dist/tui/manager/PackManager.js.map +1 -0
  113. package/dist/tui/manager/StatusView.d.ts +15 -0
  114. package/dist/tui/manager/StatusView.d.ts.map +1 -0
  115. package/dist/tui/manager/StatusView.js +10 -0
  116. package/dist/tui/manager/StatusView.js.map +1 -0
  117. package/package.json +45 -0
  118. package/scripts/install.sh +11 -0
  119. package/src/cli/packs.test.ts +213 -0
  120. package/src/cli/packs.ts +214 -0
  121. package/src/config.ts +62 -0
  122. package/src/index.ts +218 -0
  123. package/src/runtime/attestation.test.ts +69 -0
  124. package/src/runtime/attestation.ts +36 -0
  125. package/src/runtime/audit.test.ts +64 -0
  126. package/src/runtime/audit.ts +70 -0
  127. package/src/runtime/connection.test.ts +303 -0
  128. package/src/runtime/connection.ts +389 -0
  129. package/src/runtime/executor.test.ts +112 -0
  130. package/src/runtime/executor.ts +107 -0
  131. package/src/runtime/privilege.test.ts +25 -0
  132. package/src/runtime/privilege.ts +36 -0
  133. package/src/runtime/scrubber.test.ts +84 -0
  134. package/src/runtime/scrubber.ts +96 -0
  135. package/src/system/scanner.test.ts +154 -0
  136. package/src/system/scanner.ts +133 -0
  137. package/src/tui/installer/InstallerApp.tsx +86 -0
  138. package/src/tui/installer/StepComplete.tsx +94 -0
  139. package/src/tui/installer/StepHub.tsx +111 -0
  140. package/src/tui/installer/StepPacks.tsx +73 -0
  141. package/src/tui/installer/StepPermissions.tsx +104 -0
  142. package/src/tui/installer/StepScan.tsx +82 -0
  143. package/src/tui/manager/ActivityLog.tsx +57 -0
  144. package/src/tui/manager/AuditView.tsx +73 -0
  145. package/src/tui/manager/ManagerApp.tsx +157 -0
  146. package/src/tui/manager/PackManager.tsx +71 -0
  147. package/src/tui/manager/StatusView.tsx +103 -0
  148. package/tsconfig.json +13 -0
  149. package/vitest.config.ts +8 -0
package/dist/index.js ADDED
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+ import os from 'node:os';
3
+ import { handlePacksCommand } from './cli/packs.js';
4
+ import { getConfigPath, loadConfig, saveConfig } from './config.js';
5
+ import { AgentConnection, enrollWithHub } from './runtime/connection.js';
6
+ import { ProbeExecutor } from './runtime/executor.js';
7
+ import { checkNotRoot } from './runtime/privilege.js';
8
+ import { buildPatterns } from './runtime/scrubber.js';
9
+ const args = process.argv.slice(2);
10
+ const command = args[0];
11
+ function hasFlag(flag) {
12
+ return args.includes(flag);
13
+ }
14
+ function printUsage() {
15
+ console.log('Usage: sonde [command]');
16
+ console.log('');
17
+ console.log('Commands:');
18
+ console.log(' (none) Launch management TUI (if enrolled)');
19
+ console.log(' install Interactive guided setup (enroll + scan + packs)');
20
+ console.log(' enroll Enroll this agent with a hub');
21
+ console.log(' start Start the agent (TUI by default, --headless for daemon)');
22
+ console.log(' status Show agent status');
23
+ console.log(' packs Manage packs (list, scan, install, uninstall)');
24
+ console.log('');
25
+ console.log('Enroll options:');
26
+ console.log(' --hub <url> Hub URL (e.g. http://localhost:3000)');
27
+ console.log(' --key <key> API key for authentication');
28
+ console.log(' --name <name> Agent name (default: hostname)');
29
+ console.log(' --token <token> Enrollment token for mTLS cert issuance');
30
+ console.log('');
31
+ console.log('Start options:');
32
+ console.log(' --headless Run without TUI (for systemd / background)');
33
+ }
34
+ function getArg(flag) {
35
+ const idx = args.indexOf(flag);
36
+ if (idx === -1 || idx + 1 >= args.length)
37
+ return undefined;
38
+ return args[idx + 1];
39
+ }
40
+ function createRuntime(events) {
41
+ checkNotRoot();
42
+ const config = loadConfig();
43
+ if (!config) {
44
+ console.error('Error: Agent not enrolled. Run "sonde enroll" first.');
45
+ process.exit(1);
46
+ }
47
+ const executor = new ProbeExecutor(undefined, undefined, buildPatterns(config.scrubPatterns));
48
+ const connection = new AgentConnection(config, executor, events);
49
+ return { config, executor, connection };
50
+ }
51
+ async function cmdEnroll() {
52
+ const hubUrl = getArg('--hub');
53
+ const apiKey = getArg('--key');
54
+ const agentName = getArg('--name') ?? os.hostname();
55
+ const enrollmentToken = getArg('--token');
56
+ if (!hubUrl || !apiKey) {
57
+ console.error('Error: --hub and --key are required');
58
+ console.error(' sonde enroll --hub http://localhost:3000 --key your-api-key');
59
+ process.exit(1);
60
+ }
61
+ const config = { hubUrl, apiKey, agentName };
62
+ if (enrollmentToken) {
63
+ config.enrollmentToken = enrollmentToken;
64
+ }
65
+ saveConfig(config);
66
+ const executor = new ProbeExecutor();
67
+ console.log(`Enrolling with hub at ${hubUrl}...`);
68
+ const { agentId, certIssued } = await enrollWithHub(config, executor);
69
+ config.agentId = agentId;
70
+ // Clear the one-time token after use
71
+ config.enrollmentToken = undefined;
72
+ saveConfig(config);
73
+ console.log('Agent enrolled successfully.');
74
+ console.log(` Hub: ${hubUrl}`);
75
+ console.log(` Name: ${agentName}`);
76
+ console.log(` Agent ID: ${agentId}`);
77
+ console.log(` Config: ${getConfigPath()}`);
78
+ if (certIssued) {
79
+ console.log(' mTLS: Client certificate issued and saved');
80
+ }
81
+ console.log('');
82
+ console.log('Run "sonde start" to connect.');
83
+ }
84
+ function cmdStart() {
85
+ const { config, connection } = createRuntime({
86
+ onConnected: (agentId) => {
87
+ console.log(`Connected to hub (agentId: ${agentId})`);
88
+ },
89
+ onDisconnected: () => {
90
+ console.log('Disconnected from hub, reconnecting...');
91
+ },
92
+ onError: (err) => {
93
+ console.error(`Connection error: ${err.message}`);
94
+ },
95
+ onRegistered: (agentId) => {
96
+ config.agentId = agentId;
97
+ saveConfig(config);
98
+ },
99
+ });
100
+ console.log('Sonde Agent v0.1.0');
101
+ console.log(` Name: ${config.agentName}`);
102
+ console.log(` Hub: ${config.hubUrl}`);
103
+ console.log('');
104
+ connection.start();
105
+ process.on('SIGINT', () => {
106
+ console.log('\nShutting down...');
107
+ connection.stop();
108
+ process.exit(0);
109
+ });
110
+ }
111
+ async function cmdManager() {
112
+ const { render } = await import('ink');
113
+ const { createElement } = await import('react');
114
+ const { ManagerApp } = await import('./tui/manager/ManagerApp.js');
115
+ const { waitUntilExit } = render(createElement(ManagerApp, { createRuntime }));
116
+ await waitUntilExit();
117
+ }
118
+ function cmdStatus() {
119
+ const config = loadConfig();
120
+ if (!config) {
121
+ console.log('Status: Not enrolled');
122
+ console.log(`Run "sonde enroll" to get started.`);
123
+ return;
124
+ }
125
+ console.log('Sonde Agent Status');
126
+ console.log(` Name: ${config.agentName}`);
127
+ console.log(` Hub: ${config.hubUrl}`);
128
+ console.log(` Agent ID: ${config.agentId ?? '(not yet assigned)'}`);
129
+ console.log(` Config: ${getConfigPath()}`);
130
+ }
131
+ async function cmdInstall() {
132
+ const initialHubUrl = getArg('--hub');
133
+ const { render } = await import('ink');
134
+ const { createElement } = await import('react');
135
+ const { InstallerApp } = await import('./tui/installer/InstallerApp.js');
136
+ const { waitUntilExit } = render(createElement(InstallerApp, { initialHubUrl }));
137
+ await waitUntilExit();
138
+ }
139
+ switch (command) {
140
+ case 'install':
141
+ cmdInstall().catch((err) => {
142
+ console.error(err.message);
143
+ process.exit(1);
144
+ });
145
+ break;
146
+ case 'enroll':
147
+ cmdEnroll().catch((err) => {
148
+ console.error(`Enrollment failed: ${err.message}`);
149
+ process.exit(1);
150
+ });
151
+ break;
152
+ case 'start':
153
+ if (hasFlag('--headless')) {
154
+ cmdStart();
155
+ }
156
+ else {
157
+ cmdManager().catch((err) => {
158
+ console.error(err.message);
159
+ process.exit(1);
160
+ });
161
+ }
162
+ break;
163
+ case 'status':
164
+ cmdStatus();
165
+ break;
166
+ case 'packs':
167
+ handlePacksCommand(args.slice(1));
168
+ break;
169
+ default:
170
+ if (command) {
171
+ printUsage();
172
+ console.error(`\nUnknown command: ${command}`);
173
+ process.exit(1);
174
+ }
175
+ else {
176
+ // No command: launch TUI if enrolled, otherwise show usage
177
+ const config = loadConfig();
178
+ if (config) {
179
+ cmdManager().catch((err) => {
180
+ console.error(err.message);
181
+ process.exit(1);
182
+ });
183
+ }
184
+ else {
185
+ printUsage();
186
+ }
187
+ }
188
+ break;
189
+ }
190
+ export { createRuntime };
191
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { AttestationData } from '@sonde/shared';
2
+ import type { AgentConfig } from '../config.js';
3
+ import type { ProbeExecutor } from './executor.js';
4
+ /** SHA-256 hex of a file. Returns empty string on any error. */
5
+ export declare function hashFile(filePath: string): string;
6
+ /** SHA-256 hex of config with sensitive fields stripped, keys sorted for determinism. */
7
+ export declare function hashConfig(config: AgentConfig): string;
8
+ export declare function generateAttestation(config: AgentConfig, executor: ProbeExecutor): AttestationData;
9
+ //# sourceMappingURL=attestation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation.d.ts","sourceRoot":"","sources":["../../src/runtime/attestation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,gEAAgE;AAChE,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,yFAAyF;AACzF,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAItD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,GAAG,eAAe,CAWjG"}
@@ -0,0 +1,32 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ /** SHA-256 hex of a file. Returns empty string on any error. */
5
+ export function hashFile(filePath) {
6
+ try {
7
+ const data = fs.readFileSync(filePath);
8
+ return crypto.createHash('sha256').update(data).digest('hex');
9
+ }
10
+ catch {
11
+ return '';
12
+ }
13
+ }
14
+ /** SHA-256 hex of config with sensitive fields stripped, keys sorted for determinism. */
15
+ export function hashConfig(config) {
16
+ const { apiKey: _, enrollmentToken: _t, ...rest } = config;
17
+ const sorted = JSON.stringify(rest, Object.keys(rest).sort());
18
+ return crypto.createHash('sha256').update(sorted).digest('hex');
19
+ }
20
+ export function generateAttestation(config, executor) {
21
+ return {
22
+ osVersion: `${os.platform()} ${os.release()} ${os.arch()}`,
23
+ binaryHash: hashFile(process.argv[1] ?? ''),
24
+ installedPacks: executor.getLoadedPacks().map((p) => ({
25
+ name: p.name,
26
+ version: p.version,
27
+ })),
28
+ configHash: hashConfig(config),
29
+ nodeVersion: process.version,
30
+ };
31
+ }
32
+ //# sourceMappingURL=attestation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation.js","sourceRoot":"","sources":["../../src/runtime/attestation.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AAKzB,gEAAgE;AAChE,MAAM,UAAU,QAAQ,CAAC,QAAgB;IACvC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,UAAU,CAAC,MAAmB;IAC5C,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9D,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAmB,EAAE,QAAuB;IAC9E,OAAO;QACL,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;QAC1D,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,cAAc,EAAE,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpD,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC,CAAC;QACH,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC;QAC9B,WAAW,EAAE,OAAO,CAAC,OAAO;KAC7B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=attestation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation.test.d.ts","sourceRoot":"","sources":["../../src/runtime/attestation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { generateAttestation, hashConfig, hashFile } from './attestation.js';
3
+ import { ProbeExecutor } from './executor.js';
4
+ function makeConfig(overrides) {
5
+ return {
6
+ hubUrl: 'http://localhost:3000',
7
+ apiKey: 'test-key',
8
+ agentName: 'test-agent',
9
+ ...overrides,
10
+ };
11
+ }
12
+ function makeExecutor() {
13
+ return new ProbeExecutor(new Map());
14
+ }
15
+ describe('generateAttestation', () => {
16
+ it('returns all required fields', () => {
17
+ const att = generateAttestation(makeConfig(), makeExecutor());
18
+ expect(att).toHaveProperty('osVersion');
19
+ expect(att).toHaveProperty('binaryHash');
20
+ expect(att).toHaveProperty('installedPacks');
21
+ expect(att).toHaveProperty('configHash');
22
+ expect(att).toHaveProperty('nodeVersion');
23
+ });
24
+ it('osVersion contains platform info', () => {
25
+ const att = generateAttestation(makeConfig(), makeExecutor());
26
+ expect(att.osVersion).toContain(process.platform);
27
+ });
28
+ it('nodeVersion matches process.version', () => {
29
+ const att = generateAttestation(makeConfig(), makeExecutor());
30
+ expect(att.nodeVersion).toBe(process.version);
31
+ });
32
+ it('installedPacks reflects loaded packs', () => {
33
+ const att = generateAttestation(makeConfig(), makeExecutor());
34
+ // Empty map → no packs
35
+ expect(att.installedPacks).toEqual([]);
36
+ });
37
+ });
38
+ describe('hashConfig', () => {
39
+ it('is deterministic for same config', () => {
40
+ const cfg = makeConfig();
41
+ expect(hashConfig(cfg)).toBe(hashConfig(cfg));
42
+ });
43
+ it('ignores apiKey changes', () => {
44
+ const a = hashConfig(makeConfig({ apiKey: 'key-a' }));
45
+ const b = hashConfig(makeConfig({ apiKey: 'key-b' }));
46
+ expect(a).toBe(b);
47
+ });
48
+ it('ignores enrollmentToken changes', () => {
49
+ const a = hashConfig(makeConfig({ enrollmentToken: 'tok-a' }));
50
+ const b = hashConfig(makeConfig({ enrollmentToken: 'tok-b' }));
51
+ expect(a).toBe(b);
52
+ });
53
+ });
54
+ describe('hashFile', () => {
55
+ it('returns empty string for missing file', () => {
56
+ expect(hashFile('/nonexistent/path/to/file')).toBe('');
57
+ });
58
+ });
59
+ //# sourceMappingURL=attestation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation.test.js","sourceRoot":"","sources":["../../src/runtime/attestation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface AgentAuditEntry {
2
+ timestamp: string;
3
+ probe: string;
4
+ status: string;
5
+ durationMs: number;
6
+ prevHash: string;
7
+ }
8
+ export declare class AgentAuditLog {
9
+ private entries;
10
+ private capacity;
11
+ constructor(capacity?: number);
12
+ log(probe: string, status: string, durationMs: number): void;
13
+ getRecent(n?: number): AgentAuditEntry[];
14
+ verifyChain(): {
15
+ valid: boolean;
16
+ brokenAt?: number;
17
+ };
18
+ }
19
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/runtime/audit.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,SAAmB;IAIvC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAyB5D,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE;IAKxC,WAAW,IAAI;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;CAmBrD"}
@@ -0,0 +1,52 @@
1
+ import crypto from 'node:crypto';
2
+ const DEFAULT_CAPACITY = 1000;
3
+ export class AgentAuditLog {
4
+ entries = [];
5
+ capacity;
6
+ constructor(capacity = DEFAULT_CAPACITY) {
7
+ this.capacity = capacity;
8
+ }
9
+ log(probe, status, durationMs) {
10
+ const prevHash = this.entries.length > 0
11
+ ? crypto
12
+ .createHash('sha256')
13
+ .update(JSON.stringify(this.entries[this.entries.length - 1]))
14
+ .digest('hex')
15
+ : '';
16
+ const entry = {
17
+ timestamp: new Date().toISOString(),
18
+ probe,
19
+ status,
20
+ durationMs,
21
+ prevHash,
22
+ };
23
+ this.entries.push(entry);
24
+ // Ring buffer: drop oldest when over capacity
25
+ if (this.entries.length > this.capacity) {
26
+ this.entries.shift();
27
+ }
28
+ }
29
+ getRecent(n) {
30
+ if (n === undefined)
31
+ return [...this.entries];
32
+ return this.entries.slice(-n);
33
+ }
34
+ verifyChain() {
35
+ if (this.entries.length === 0)
36
+ return { valid: true };
37
+ const first = this.entries[0];
38
+ if (first && first.prevHash !== '') {
39
+ return { valid: false, brokenAt: 0 };
40
+ }
41
+ for (let i = 1; i < this.entries.length; i++) {
42
+ const prev = this.entries[i - 1];
43
+ const curr = this.entries[i];
44
+ const expectedHash = crypto.createHash('sha256').update(JSON.stringify(prev)).digest('hex');
45
+ if (curr.prevHash !== expectedHash) {
46
+ return { valid: false, brokenAt: i };
47
+ }
48
+ }
49
+ return { valid: true };
50
+ }
51
+ }
52
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/runtime/audit.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAUjC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,MAAM,OAAO,aAAa;IAChB,OAAO,GAAsB,EAAE,CAAC;IAChC,QAAQ,CAAS;IAEzB,YAAY,QAAQ,GAAG,gBAAgB;QACrC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,GAAG,CAAC,KAAa,EAAE,MAAc,EAAE,UAAkB;QACnD,MAAM,QAAQ,GACZ,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,CAAC,MAAM;iBACH,UAAU,CAAC,QAAQ,CAAC;iBACpB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;iBAC7D,MAAM,CAAC,KAAK,CAAC;YAClB,CAAC,CAAC,EAAE,CAAC;QAET,MAAM,KAAK,GAAoB;YAC7B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,KAAK;YACL,MAAM;YACN,UAAU;YACV,QAAQ;SACT,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEzB,8CAA8C;QAC9C,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;IAED,SAAS,CAAC,CAAU;QAClB,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAEtD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,EAAE,EAAE,CAAC;YACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QACvC,CAAC;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAoB,CAAC;YACpD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAoB,CAAC;YAChD,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5F,IAAI,IAAI,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;gBACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;YACvC,CAAC;QACH,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=audit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.test.d.ts","sourceRoot":"","sources":["../../src/runtime/audit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { AgentAuditLog } from './audit.js';
3
+ describe('AgentAuditLog', () => {
4
+ it('logs entries and verifies chain', () => {
5
+ const log = new AgentAuditLog();
6
+ log.log('system.disk.usage', 'success', 10);
7
+ log.log('system.memory.usage', 'success', 20);
8
+ log.log('system.cpu.usage', 'error', 30);
9
+ const entries = log.getRecent();
10
+ expect(entries).toHaveLength(3);
11
+ expect(entries[0]?.prevHash).toBe('');
12
+ expect(entries[1]?.prevHash).not.toBe('');
13
+ expect(log.verifyChain()).toEqual({ valid: true });
14
+ });
15
+ it('ring buffer cap works', () => {
16
+ const log = new AgentAuditLog(3);
17
+ log.log('p1', 'success', 1);
18
+ log.log('p2', 'success', 2);
19
+ log.log('p3', 'success', 3);
20
+ log.log('p4', 'success', 4);
21
+ const entries = log.getRecent();
22
+ expect(entries).toHaveLength(3);
23
+ expect(entries[0]?.probe).toBe('p2');
24
+ expect(entries[2]?.probe).toBe('p4');
25
+ });
26
+ it('empty log is valid', () => {
27
+ const log = new AgentAuditLog();
28
+ expect(log.verifyChain()).toEqual({ valid: true });
29
+ });
30
+ it('getRecent(n) returns last n entries', () => {
31
+ const log = new AgentAuditLog();
32
+ log.log('p1', 'success', 1);
33
+ log.log('p2', 'success', 2);
34
+ log.log('p3', 'success', 3);
35
+ const last2 = log.getRecent(2);
36
+ expect(last2).toHaveLength(2);
37
+ expect(last2[0]?.probe).toBe('p2');
38
+ expect(last2[1]?.probe).toBe('p3');
39
+ });
40
+ it('chain after ring buffer eviction still verifies within remaining entries', () => {
41
+ const log = new AgentAuditLog(2);
42
+ log.log('p1', 'success', 1);
43
+ log.log('p2', 'success', 2);
44
+ log.log('p3', 'success', 3);
45
+ // After eviction, the first remaining entry's prevHash won't match empty string
46
+ // verifyChain checks what's in the buffer, genesis may have non-empty prevHash
47
+ const result = log.verifyChain();
48
+ // First entry in buffer (p2) has a prevHash from p1, which is no longer genesis
49
+ // This is expected: a truncated chain won't verify from genesis
50
+ expect(result.valid).toBe(false);
51
+ });
52
+ });
53
+ //# sourceMappingURL=audit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.test.js","sourceRoot":"","sources":["../../src/runtime/audit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import type { AgentConfig } from '../config.js';
2
+ import { AgentAuditLog } from './audit.js';
3
+ import type { ProbeExecutor } from './executor.js';
4
+ export interface ConnectionEvents {
5
+ onConnected?: (agentId: string) => void;
6
+ onDisconnected?: () => void;
7
+ onError?: (error: Error) => void;
8
+ onRegistered?: (agentId: string) => void;
9
+ onProbeCompleted?: (probe: string, status: string, durationMs: number) => void;
10
+ }
11
+ /**
12
+ * One-shot enrollment: connect to hub, register, get agentId, disconnect.
13
+ * If enrollmentToken is set in config, includes it in registration for cert-based enrollment.
14
+ * Returns { agentId, certIssued } — certIssued is true if certs were saved.
15
+ */
16
+ export declare function enrollWithHub(config: AgentConfig, executor: ProbeExecutor): Promise<{
17
+ agentId: string;
18
+ certIssued: boolean;
19
+ }>;
20
+ export declare class AgentConnection {
21
+ private config;
22
+ private executor;
23
+ private events;
24
+ private ws;
25
+ private heartbeatTimer;
26
+ private reconnectTimer;
27
+ private reconnectAttempts;
28
+ private agentId;
29
+ private running;
30
+ private privateKeyPem;
31
+ private caCertPem;
32
+ private auditLog;
33
+ constructor(config: AgentConfig, executor: ProbeExecutor, events?: ConnectionEvents);
34
+ /** Start the connection (connect + auto-reconnect loop) */
35
+ start(): void;
36
+ /** Stop the connection cleanly */
37
+ stop(): void;
38
+ /** Whether we're currently connected */
39
+ isConnected(): boolean;
40
+ /** Get the assigned agent ID (set after registration) */
41
+ getAgentId(): string | undefined;
42
+ private connect;
43
+ private handleMessage;
44
+ private handleAck;
45
+ private handleProbeRequest;
46
+ /** Get the agent-side audit log (for testing/inspection) */
47
+ getAuditLog(): AgentAuditLog;
48
+ private sendRegister;
49
+ private startHeartbeat;
50
+ private sendError;
51
+ private send;
52
+ private scheduleReconnect;
53
+ private clearTimers;
54
+ }
55
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/runtime/connection.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAChF;AAQD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC,CAmFnD;AAwBD,qBAAa,eAAe;IAYxB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IAbhB,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,QAAQ,CAAuB;gBAG7B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,aAAa,EACvB,MAAM,GAAE,gBAAqB;IAoBvC,2DAA2D;IAC3D,KAAK,IAAI,IAAI;IAKb,kCAAkC;IAClC,IAAI,IAAI,IAAI;IASZ,wCAAwC;IACxC,WAAW,IAAI,OAAO;IAItB,yDAAyD;IACzD,UAAU,IAAI,MAAM,GAAG,SAAS;IAIhC,OAAO,CAAC,OAAO;IA6Bf,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,SAAS;YASH,kBAAkB;IA0BhC,4DAA4D;IAC5D,WAAW,IAAI,aAAa;IAI5B,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,WAAW;CAUpB"}