@phigon/observer 8.2.0 → 8.3.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 (187) hide show
  1. package/README.md +194 -11
  2. package/dist/bin/guardian-runner-darwin-amd64 +0 -0
  3. package/dist/bin/guardian-runner-darwin-arm64 +0 -0
  4. package/dist/bin/guardian-runner-linux-amd64 +0 -0
  5. package/dist/bin/guardian-runner-linux-arm64 +0 -0
  6. package/dist/bin/guardian-runner-windows-amd64.exe +0 -0
  7. package/dist/bin/guardian-runner-windows-arm64.exe +0 -0
  8. package/dist/src/abortable-delay.d.ts +10 -0
  9. package/dist/src/abortable-delay.d.ts.map +1 -0
  10. package/dist/src/abortable-delay.js +21 -0
  11. package/dist/src/abortable-delay.js.map +1 -0
  12. package/dist/src/activity/adapters/claude.d.ts.map +1 -1
  13. package/dist/src/activity/adapters/claude.js +9 -1
  14. package/dist/src/activity/adapters/claude.js.map +1 -1
  15. package/dist/src/activity/adapters/openai-compatible.d.ts.map +1 -1
  16. package/dist/src/activity/adapters/openai-compatible.js +9 -1
  17. package/dist/src/activity/adapters/openai-compatible.js.map +1 -1
  18. package/dist/src/activity/collector.d.ts +31 -1
  19. package/dist/src/activity/collector.d.ts.map +1 -1
  20. package/dist/src/activity/collector.js +337 -77
  21. package/dist/src/activity/collector.js.map +1 -1
  22. package/dist/src/activity/ingest.d.ts +9 -0
  23. package/dist/src/activity/ingest.d.ts.map +1 -1
  24. package/dist/src/activity/ingest.js +92 -3
  25. package/dist/src/activity/ingest.js.map +1 -1
  26. package/dist/src/activity/json-document-source.d.ts +15 -0
  27. package/dist/src/activity/json-document-source.d.ts.map +1 -1
  28. package/dist/src/activity/json-document-source.js +19 -2
  29. package/dist/src/activity/json-document-source.js.map +1 -1
  30. package/dist/src/activity/native-capabilities.d.ts.map +1 -1
  31. package/dist/src/activity/native-capabilities.js +8 -12
  32. package/dist/src/activity/native-capabilities.js.map +1 -1
  33. package/dist/src/activity/opencode-sqlite-source.js +1 -0
  34. package/dist/src/activity/opencode-sqlite-source.js.map +1 -1
  35. package/dist/src/activity/source-reader.d.ts +44 -3
  36. package/dist/src/activity/source-reader.d.ts.map +1 -1
  37. package/dist/src/activity/source-reader.js +325 -86
  38. package/dist/src/activity/source-reader.js.map +1 -1
  39. package/dist/src/agent-action-executor.d.ts +5 -0
  40. package/dist/src/agent-action-executor.d.ts.map +1 -1
  41. package/dist/src/agent-action-executor.js +9 -6
  42. package/dist/src/agent-action-executor.js.map +1 -1
  43. package/dist/src/atomic-replace.d.ts +7 -0
  44. package/dist/src/atomic-replace.d.ts.map +1 -1
  45. package/dist/src/atomic-replace.js +28 -3
  46. package/dist/src/atomic-replace.js.map +1 -1
  47. package/dist/src/bridge-journal.d.ts +32 -0
  48. package/dist/src/bridge-journal.d.ts.map +1 -0
  49. package/dist/src/bridge-journal.js +113 -0
  50. package/dist/src/bridge-journal.js.map +1 -0
  51. package/dist/src/cli.d.ts +7 -1
  52. package/dist/src/cli.d.ts.map +1 -1
  53. package/dist/src/cli.js +490 -43
  54. package/dist/src/cli.js.map +1 -1
  55. package/dist/src/collection-notice.d.ts +34 -0
  56. package/dist/src/collection-notice.d.ts.map +1 -0
  57. package/dist/src/collection-notice.js +73 -0
  58. package/dist/src/collection-notice.js.map +1 -0
  59. package/dist/src/config.d.ts +26 -0
  60. package/dist/src/config.d.ts.map +1 -1
  61. package/dist/src/config.js +88 -33
  62. package/dist/src/config.js.map +1 -1
  63. package/dist/src/content-redaction.d.ts +17 -1
  64. package/dist/src/content-redaction.d.ts.map +1 -1
  65. package/dist/src/content-redaction.js +44 -3
  66. package/dist/src/content-redaction.js.map +1 -1
  67. package/dist/src/credential-store.d.ts +20 -1
  68. package/dist/src/credential-store.d.ts.map +1 -1
  69. package/dist/src/credential-store.js +27 -3
  70. package/dist/src/credential-store.js.map +1 -1
  71. package/dist/src/discovery/engine.d.ts.map +1 -1
  72. package/dist/src/discovery/engine.js +1 -11
  73. package/dist/src/discovery/engine.js.map +1 -1
  74. package/dist/src/doctor-check.d.ts +51 -0
  75. package/dist/src/doctor-check.d.ts.map +1 -0
  76. package/dist/src/doctor-check.js +174 -0
  77. package/dist/src/doctor-check.js.map +1 -0
  78. package/dist/src/enroll.d.ts +86 -0
  79. package/dist/src/enroll.d.ts.map +1 -0
  80. package/dist/src/enroll.js +245 -0
  81. package/dist/src/enroll.js.map +1 -0
  82. package/dist/src/entry.d.ts +3 -0
  83. package/dist/src/entry.d.ts.map +1 -0
  84. package/dist/src/entry.js +14 -0
  85. package/dist/src/entry.js.map +1 -0
  86. package/dist/src/event-queue.d.ts +13 -1
  87. package/dist/src/event-queue.d.ts.map +1 -1
  88. package/dist/src/event-queue.js +50 -5
  89. package/dist/src/event-queue.js.map +1 -1
  90. package/dist/src/event-spool.d.ts +61 -3
  91. package/dist/src/event-spool.d.ts.map +1 -1
  92. package/dist/src/event-spool.js +290 -41
  93. package/dist/src/event-spool.js.map +1 -1
  94. package/dist/src/generated/phigon/v1/identity_pb.d.ts +7 -0
  95. package/dist/src/generated/phigon/v1/identity_pb.d.ts.map +1 -1
  96. package/dist/src/generated/phigon/v1/identity_pb.js +1 -1
  97. package/dist/src/generated/phigon/v1/identity_pb.js.map +1 -1
  98. package/dist/src/guardian-decision-journal.d.ts.map +1 -1
  99. package/dist/src/guardian-decision-journal.js +4 -20
  100. package/dist/src/guardian-decision-journal.js.map +1 -1
  101. package/dist/src/guardian-managed-exec.js +6 -19
  102. package/dist/src/guardian-managed-exec.js.map +1 -1
  103. package/dist/src/guardian-process-monitor.d.ts +1 -0
  104. package/dist/src/guardian-process-monitor.d.ts.map +1 -1
  105. package/dist/src/guardian-process-monitor.js +74 -26
  106. package/dist/src/guardian-process-monitor.js.map +1 -1
  107. package/dist/src/health.d.ts +19 -1
  108. package/dist/src/health.d.ts.map +1 -1
  109. package/dist/src/health.js +22 -1
  110. package/dist/src/health.js.map +1 -1
  111. package/dist/src/historical-identity-store.d.ts +8 -1
  112. package/dist/src/historical-identity-store.d.ts.map +1 -1
  113. package/dist/src/historical-identity-store.js +26 -9
  114. package/dist/src/historical-identity-store.js.map +1 -1
  115. package/dist/src/index.d.ts +2 -0
  116. package/dist/src/index.d.ts.map +1 -1
  117. package/dist/src/index.js +2 -0
  118. package/dist/src/index.js.map +1 -1
  119. package/dist/src/installation.d.ts +2 -0
  120. package/dist/src/installation.d.ts.map +1 -1
  121. package/dist/src/installation.js +3 -1
  122. package/dist/src/installation.js.map +1 -1
  123. package/dist/src/instance-lock.d.ts +45 -0
  124. package/dist/src/instance-lock.d.ts.map +1 -0
  125. package/dist/src/instance-lock.js +243 -0
  126. package/dist/src/instance-lock.js.map +1 -0
  127. package/dist/src/machine-command-executor.d.ts +2 -2
  128. package/dist/src/machine-command-executor.d.ts.map +1 -1
  129. package/dist/src/machine-command-executor.js +7 -20
  130. package/dist/src/machine-command-executor.js.map +1 -1
  131. package/dist/src/node-version.d.ts +8 -0
  132. package/dist/src/node-version.d.ts.map +1 -0
  133. package/dist/src/node-version.js +17 -0
  134. package/dist/src/node-version.js.map +1 -0
  135. package/dist/src/observer-log.d.ts +50 -0
  136. package/dist/src/observer-log.d.ts.map +1 -0
  137. package/dist/src/observer-log.js +141 -0
  138. package/dist/src/observer-log.js.map +1 -0
  139. package/dist/src/pair.d.ts +68 -1
  140. package/dist/src/pair.d.ts.map +1 -1
  141. package/dist/src/pair.js +204 -66
  142. package/dist/src/pair.js.map +1 -1
  143. package/dist/src/private-directory.d.ts +6 -0
  144. package/dist/src/private-directory.d.ts.map +1 -1
  145. package/dist/src/private-directory.js +33 -2
  146. package/dist/src/private-directory.js.map +1 -1
  147. package/dist/src/proxy.d.ts +68 -0
  148. package/dist/src/proxy.d.ts.map +1 -0
  149. package/dist/src/proxy.js +209 -0
  150. package/dist/src/proxy.js.map +1 -0
  151. package/dist/src/purge.d.ts +17 -0
  152. package/dist/src/purge.d.ts.map +1 -0
  153. package/dist/src/purge.js +84 -0
  154. package/dist/src/purge.js.map +1 -0
  155. package/dist/src/remove-machine.d.ts +5 -1
  156. package/dist/src/remove-machine.d.ts.map +1 -1
  157. package/dist/src/remove-machine.js +28 -14
  158. package/dist/src/remove-machine.js.map +1 -1
  159. package/dist/src/server-authority.d.ts +5 -2
  160. package/dist/src/server-authority.d.ts.map +1 -1
  161. package/dist/src/server-authority.js +10 -6
  162. package/dist/src/server-authority.js.map +1 -1
  163. package/dist/src/server-clock.d.ts +32 -0
  164. package/dist/src/server-clock.d.ts.map +1 -0
  165. package/dist/src/server-clock.js +72 -0
  166. package/dist/src/server-clock.js.map +1 -0
  167. package/dist/src/service-command.d.ts +20 -0
  168. package/dist/src/service-command.d.ts.map +1 -0
  169. package/dist/src/service-command.js +136 -0
  170. package/dist/src/service-command.js.map +1 -0
  171. package/dist/src/service.d.ts +98 -0
  172. package/dist/src/service.d.ts.map +1 -0
  173. package/dist/src/service.js +472 -0
  174. package/dist/src/service.js.map +1 -0
  175. package/dist/src/stream-client.d.ts +18 -0
  176. package/dist/src/stream-client.d.ts.map +1 -1
  177. package/dist/src/stream-client.js +91 -16
  178. package/dist/src/stream-client.js.map +1 -1
  179. package/dist/src/stream-state.d.ts +2 -0
  180. package/dist/src/stream-state.d.ts.map +1 -1
  181. package/dist/src/stream-state.js +3 -1
  182. package/dist/src/stream-state.js.map +1 -1
  183. package/dist/src/user-notices.d.ts +11 -0
  184. package/dist/src/user-notices.d.ts.map +1 -1
  185. package/dist/src/user-notices.js +24 -0
  186. package/dist/src/user-notices.js.map +1 -1
  187. package/package.json +7 -7
@@ -0,0 +1,472 @@
1
+ import { execFile } from "node:child_process";
2
+ import { createHash, randomUUID } from "node:crypto";
3
+ import { chmod, mkdir, readFile, rm, stat, unlink, writeFile } from "node:fs/promises";
4
+ import { dirname, isAbsolute, join, posix, win32 } from "node:path";
5
+ import { setTimeout as delay } from "node:timers/promises";
6
+ import { atomicReplace } from "./atomic-replace.js";
7
+ import { makeDirectoryPrivate } from "./private-directory.js";
8
+ export const serviceSettingsFileName = "service-settings.json";
9
+ const settingsVersion = 1;
10
+ const maxSettingsBytes = 256 * 1024;
11
+ const maxSettingValueBytes = 32 * 1024;
12
+ export function servicePlatform(platform) {
13
+ if (platform === "win32")
14
+ return "windows";
15
+ if (platform === "darwin")
16
+ return "macos";
17
+ if (platform === "linux")
18
+ return "linux";
19
+ return undefined;
20
+ }
21
+ /**
22
+ * The service's name. One observer runs per data directory, so a directory
23
+ * other than the default gets its own service, named with a short digest
24
+ * of its path.
25
+ */
26
+ export function serviceName(context) {
27
+ const path = (context.platform === "windows" ? win32 : posix).resolve(context.dataDirectory);
28
+ const suffix = context.defaultDataDirectory
29
+ ? ""
30
+ : createHash("sha256").update(context.platform === "windows" ? path.toLowerCase() : path).digest("hex").slice(0, 8);
31
+ if (context.platform === "windows")
32
+ return suffix === "" ? "Phigon Observer" : `Phigon Observer ${suffix}`;
33
+ if (context.platform === "macos")
34
+ return suffix === "" ? "com.phigon.observer" : `com.phigon.observer.${suffix}`;
35
+ return suffix === "" ? "phigon-observer" : `phigon-observer-${suffix}`;
36
+ }
37
+ export function serviceSettingsPath(dataDirectory) {
38
+ return join(dataDirectory, serviceSettingsFileName);
39
+ }
40
+ /** Where the definition file lives; Windows keeps it in Task Scheduler. */
41
+ export function serviceDefinitionPath(context) {
42
+ if (context.platform === "macos") {
43
+ return join(context.homeDirectory, "Library", "LaunchAgents", `${serviceName(context)}.plist`);
44
+ }
45
+ if (context.platform === "linux") {
46
+ const configHome = context.configHome !== undefined && isAbsolute(context.configHome)
47
+ ? context.configHome
48
+ : join(context.homeDirectory, ".config");
49
+ return join(configHome, "systemd", "user", `${serviceName(context)}.service`);
50
+ }
51
+ return undefined;
52
+ }
53
+ function checkedPath(value, platform, label) {
54
+ const absolute = (platform === "windows" ? /^[A-Za-z]:[\\/]/u.test(value) || value.startsWith("\\\\") : value.startsWith("/")) ||
55
+ // Tests build another system's service from this computer's folders.
56
+ (servicePlatform(process.platform) !== platform && isAbsolute(value));
57
+ if (!absolute || /[\u0000-\u001f\u007f]/u.test(value) || (platform === "windows" && /["%]/u.test(value))) {
58
+ throw new Error(`The ${label} path ${JSON.stringify(value)} cannot be used by a background service. Use a plain absolute path.`);
59
+ }
60
+ return value;
61
+ }
62
+ /** The command the service runs. */
63
+ export function serviceCommand(context) {
64
+ return [
65
+ checkedPath(context.nodePath, context.platform, "Node.js"),
66
+ checkedPath(context.entryPath, context.platform, "observer"),
67
+ "run",
68
+ "--service-settings",
69
+ checkedPath((context.platform === "windows" ? win32 : posix).join(context.dataDirectory, serviceSettingsFileName), context.platform, "data directory"),
70
+ ];
71
+ }
72
+ function xml(value) {
73
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;")
74
+ .replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
75
+ }
76
+ function localTimestamp(date) {
77
+ const pad = (value) => value.toString().padStart(2, "0");
78
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T` +
79
+ `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
80
+ }
81
+ /**
82
+ * Task Scheduler XML. The task starts at sign-in and is retried every minute
83
+ * (a running copy is left alone), so an observer that stops is started again
84
+ * within a minute. conhost --headless keeps a console window from opening;
85
+ * it does not pass on the exit code, so the minute trigger, not the failure
86
+ * setting, is what restarts it.
87
+ */
88
+ export function windowsTaskXml(context) {
89
+ const [node, entry, ...rest] = serviceCommand(context);
90
+ const conhost = `${checkedPath(context.systemRoot ?? "C:\\Windows", "windows", "Windows")}\\System32\\conhost.exe`;
91
+ const quote = (value) => /^[A-Za-z0-9_.:\\/-]+$/u.test(value) ? value : `"${value}"`;
92
+ const argumentsText = ["--headless", `"${node}"`, `"${entry}"`, ...rest.map(quote)].join(" ");
93
+ const user = xml(context.user);
94
+ return `<?xml version="1.0" encoding="UTF-16"?>
95
+ <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
96
+ <RegistrationInfo>
97
+ <Author>Phigon observer</Author>
98
+ <Description>Collects AI agent activity for this user under the consent the computer's owner gave, and sends it to the Phigon workspace. Remove it with: phigon-observer service uninstall</Description>
99
+ <URI>\\${xml(serviceName(context))}</URI>
100
+ </RegistrationInfo>
101
+ <Triggers>
102
+ <LogonTrigger>
103
+ <Enabled>true</Enabled>
104
+ <UserId>${user}</UserId>
105
+ </LogonTrigger>
106
+ <TimeTrigger>
107
+ <Enabled>true</Enabled>
108
+ <StartBoundary>${localTimestamp((context.now ?? (() => new Date()))())}</StartBoundary>
109
+ <Repetition>
110
+ <Interval>PT1M</Interval>
111
+ <StopAtDurationEnd>false</StopAtDurationEnd>
112
+ </Repetition>
113
+ </TimeTrigger>
114
+ </Triggers>
115
+ <Principals>
116
+ <Principal id="Author">
117
+ <UserId>${user}</UserId>
118
+ <LogonType>InteractiveToken</LogonType>
119
+ <RunLevel>LeastPrivilege</RunLevel>
120
+ </Principal>
121
+ </Principals>
122
+ <Settings>
123
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
124
+ <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
125
+ <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
126
+ <AllowHardTerminate>true</AllowHardTerminate>
127
+ <StartWhenAvailable>true</StartWhenAvailable>
128
+ <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
129
+ <IdleSettings>
130
+ <StopOnIdleEnd>false</StopOnIdleEnd>
131
+ <RestartOnIdle>false</RestartOnIdle>
132
+ </IdleSettings>
133
+ <AllowStartOnDemand>true</AllowStartOnDemand>
134
+ <Enabled>true</Enabled>
135
+ <Hidden>false</Hidden>
136
+ <RunOnlyIfIdle>false</RunOnlyIfIdle>
137
+ <WakeToRun>false</WakeToRun>
138
+ <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
139
+ <Priority>7</Priority>
140
+ <RestartOnFailure>
141
+ <Interval>PT1M</Interval>
142
+ <Count>999</Count>
143
+ </RestartOnFailure>
144
+ </Settings>
145
+ <Actions Context="Author">
146
+ <Exec>
147
+ <Command>${xml(conhost)}</Command>
148
+ <Arguments>${xml(argumentsText)}</Arguments>
149
+ <WorkingDirectory>${xml(checkedPath(context.dataDirectory, "windows", "data directory"))}</WorkingDirectory>
150
+ </Exec>
151
+ </Actions>
152
+ </Task>
153
+ `;
154
+ }
155
+ /** A LaunchAgent that starts at sign-in and is started again if it stops. */
156
+ export function launchAgentPlist(context) {
157
+ const program = serviceCommand(context).map((value) => ` <string>${xml(value)}</string>`).join("\n");
158
+ return `<?xml version="1.0" encoding="UTF-8"?>
159
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
160
+ <plist version="1.0">
161
+ <dict>
162
+ <key>Label</key>
163
+ <string>${xml(serviceName(context))}</string>
164
+ <key>ProgramArguments</key>
165
+ <array>
166
+ ${program}
167
+ </array>
168
+ <key>WorkingDirectory</key>
169
+ <string>${xml(checkedPath(context.dataDirectory, "macos", "data directory"))}</string>
170
+ <key>RunAtLoad</key>
171
+ <true/>
172
+ <key>KeepAlive</key>
173
+ <true/>
174
+ <key>ThrottleInterval</key>
175
+ <integer>30</integer>
176
+ <key>ProcessType</key>
177
+ <string>Background</string>
178
+ <key>Umask</key>
179
+ <integer>63</integer>
180
+ <key>StandardOutPath</key>
181
+ <string>/dev/null</string>
182
+ <key>StandardErrorPath</key>
183
+ <string>/dev/null</string>
184
+ </dict>
185
+ </plist>
186
+ `;
187
+ }
188
+ /** A systemd user unit, restarted when it fails. */
189
+ export function systemdUserUnit(context) {
190
+ const quoted = (value) => `"${value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"").replaceAll("%", "%%").replaceAll("$", "$$$$")}"`;
191
+ return `[Unit]
192
+ Description=Phigon observer for this user
193
+ Documentation=https://github.com/phigonai/observer#readme
194
+ StartLimitIntervalSec=0
195
+
196
+ [Service]
197
+ Type=simple
198
+ ExecStart=${serviceCommand(context).map(quoted).join(" ")}
199
+ WorkingDirectory=${checkedPath(context.dataDirectory, "linux", "data directory")}
200
+ Restart=on-failure
201
+ RestartSec=30
202
+ UMask=0077
203
+ TimeoutStopSec=20
204
+
205
+ [Install]
206
+ WantedBy=default.target
207
+ `;
208
+ }
209
+ // ---------------------------------------------------------------------------
210
+ // Settings the service runs with.
211
+ const settingNames = new Set([
212
+ "PATH",
213
+ "HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy", "NO_PROXY", "no_proxy",
214
+ "grpc_proxy", "no_grpc_proxy",
215
+ "NODE_EXTRA_CA_CERTS",
216
+ "XDG_CONFIG_HOME", "XDG_DATA_HOME", "FLATPAK_XDG_DATA_HOME", "GOOSE_PATH_ROOT",
217
+ ]);
218
+ /**
219
+ * Names that may hold a secret are never copied, even from PHIGON_*. That
220
+ * includes PHIGON_ENROLLMENT_CODE, which an enrollment script may still
221
+ * have set when it installs the service.
222
+ */
223
+ const secretName = /TOKEN|SECRET|PASSWORD|PASSPHRASE|CREDENTIAL|ENROLLMENT/u;
224
+ function allowedSetting(name) {
225
+ if (name === "PHIGON_DATA_DIR")
226
+ return false;
227
+ if (/^PHIGON_[A-Z0-9_]{1,96}$/u.test(name))
228
+ return !secretName.test(name);
229
+ return settingNames.has(name);
230
+ }
231
+ /**
232
+ * The settings from `environment` that the service needs to behave like
233
+ * this terminal: PHIGON_* settings (never a token or password), PATH for
234
+ * finding agents, proxy and certificate settings, and the folders some
235
+ * agents keep their records in. The data directory is where the file is.
236
+ */
237
+ export function serviceSettings(environment) {
238
+ const settings = {};
239
+ for (const [rawName, value] of Object.entries(environment)) {
240
+ if (value === undefined || value === "")
241
+ continue;
242
+ // Windows spells PATH as Path.
243
+ const name = rawName.toUpperCase() === "PATH" ? "PATH" : rawName;
244
+ if (!allowedSetting(name))
245
+ continue;
246
+ if (value.includes("\u0000") || Buffer.byteLength(value, "utf8") > maxSettingValueBytes)
247
+ continue;
248
+ settings[name] = value;
249
+ }
250
+ return settings;
251
+ }
252
+ export async function writeServiceSettings(dataDirectory, settings) {
253
+ await mkdir(dataDirectory, { recursive: true, mode: 0o700 });
254
+ await makeDirectoryPrivate(dataDirectory);
255
+ const path = serviceSettingsPath(dataDirectory);
256
+ const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
257
+ try {
258
+ await writeFile(temporary, `${JSON.stringify({ version: settingsVersion, environment: settings }, null, 2)}\n`, {
259
+ encoding: "utf8", flag: "wx", mode: 0o600,
260
+ });
261
+ await atomicReplace(temporary, path);
262
+ await chmod(path, 0o600);
263
+ }
264
+ catch (error) {
265
+ await rm(temporary, { force: true });
266
+ throw error;
267
+ }
268
+ return path;
269
+ }
270
+ /** Reads and checks the settings file; anything unexpected is refused. */
271
+ export async function readServiceSettings(path) {
272
+ const invalid = () => new Error(`The background service settings in ${path} are unreadable. Run phigon-observer service install again.`);
273
+ let raw;
274
+ try {
275
+ if ((await stat(path)).size > maxSettingsBytes)
276
+ throw invalid();
277
+ raw = await readFile(path, "utf8");
278
+ }
279
+ catch (error) {
280
+ if (error.code === "ENOENT") {
281
+ throw new Error(`The background service settings file ${path} is missing. Run phigon-observer service install again.`);
282
+ }
283
+ throw invalid();
284
+ }
285
+ let value;
286
+ try {
287
+ value = JSON.parse(raw);
288
+ }
289
+ catch {
290
+ throw invalid();
291
+ }
292
+ if (typeof value !== "object" || value === null || !("version" in value) || value.version !== settingsVersion ||
293
+ !("environment" in value) || typeof value.environment !== "object" || value.environment === null ||
294
+ Array.isArray(value.environment)) {
295
+ throw invalid();
296
+ }
297
+ const settings = {};
298
+ for (const [name, setting] of Object.entries(value.environment)) {
299
+ if (!allowedSetting(name) || typeof setting !== "string" || setting.includes("\u0000") ||
300
+ Buffer.byteLength(setting, "utf8") > maxSettingValueBytes) {
301
+ throw invalid();
302
+ }
303
+ settings[name] = setting;
304
+ }
305
+ return settings;
306
+ }
307
+ // ---------------------------------------------------------------------------
308
+ // Installing, removing and inspecting the service.
309
+ export class ServiceError extends Error {
310
+ }
311
+ function describe(result) {
312
+ const text = `${result.stderr} ${result.stdout}`.replace(/\s+/gu, " ").trim().slice(0, 200);
313
+ return text === "" ? `exit code ${result.code}` : text;
314
+ }
315
+ function windowsTool(context, name) {
316
+ return `${context.systemRoot ?? "C:\\Windows"}\\System32\\${name}`;
317
+ }
318
+ async function required(context, command, args, action) {
319
+ const result = await context.run(command, args);
320
+ if (result.missing === true) {
321
+ throw new ServiceError(context.platform === "linux"
322
+ ? "This computer has no systemd user session (systemctl --user), so a background service cannot be installed. Keep phigon-observer run running another way."
323
+ : `${command} is not available on this computer, so the background service could not be ${action}.`);
324
+ }
325
+ if (result.code !== 0) {
326
+ const hint = context.platform === "linux" && /bus|XDG_RUNTIME_DIR/iu.test(describe(result))
327
+ ? " Sign in to this computer as this user (a desktop or SSH session) and try again."
328
+ : context.platform === "macos" && action !== "stopped"
329
+ ? " Sign in to this Mac's desktop as this user and try again."
330
+ : "";
331
+ throw new ServiceError(`The background service could not be ${action} (${describe(result)}).${hint}`);
332
+ }
333
+ return result;
334
+ }
335
+ /**
336
+ * Installs the service, replacing an earlier definition of the same name,
337
+ * and starts it. The caller checks pairing and consent first.
338
+ */
339
+ export async function installService(context, settings) {
340
+ const name = serviceName(context);
341
+ serviceCommand(context);
342
+ const settingsFile = await writeServiceSettings(context.dataDirectory, settings);
343
+ if (context.platform === "windows") {
344
+ const definition = join(context.dataDirectory, `service-task-${randomUUID()}.xml`);
345
+ // schtasks reads task XML as UTF-16.
346
+ await writeFile(definition, Buffer.concat([Buffer.from([0xff, 0xfe]), Buffer.from(windowsTaskXml(context), "utf16le")]), { mode: 0o600 });
347
+ try {
348
+ await required(context, windowsTool(context, "schtasks.exe"), ["/Create", "/TN", name, "/XML", definition, "/F"], "installed");
349
+ }
350
+ finally {
351
+ await rm(definition, { force: true });
352
+ }
353
+ await required(context, windowsTool(context, "schtasks.exe"), ["/Run", "/TN", name], "started");
354
+ return Object.freeze({ name, platform: context.platform, definition: name, settingsFile });
355
+ }
356
+ const definition = serviceDefinitionPath(context);
357
+ await mkdir(dirname(definition), { recursive: true, mode: 0o755 });
358
+ const content = context.platform === "macos" ? launchAgentPlist(context) : systemdUserUnit(context);
359
+ const temporary = `${definition}.${randomUUID()}.tmp`;
360
+ await writeFile(temporary, content, { encoding: "utf8", mode: 0o644 });
361
+ await atomicReplace(temporary, definition);
362
+ // launchd and systemd refuse a definition others can write to.
363
+ await chmod(definition, 0o644);
364
+ if (context.platform === "macos") {
365
+ const domain = `gui/${context.user}`;
366
+ await context.run("launchctl", ["bootout", `${domain}/${name}`]);
367
+ await context.run("launchctl", ["enable", `${domain}/${name}`]);
368
+ // launchd can still be unloading the old definition for a moment.
369
+ for (let attempt = 0;; attempt++) {
370
+ const result = await context.run("launchctl", ["bootstrap", domain, definition]);
371
+ if (result.code === 0 && result.missing !== true)
372
+ break;
373
+ if (attempt >= 4 || result.missing === true) {
374
+ await required(context, "launchctl", ["bootstrap", domain, definition], "started");
375
+ break;
376
+ }
377
+ await (context.wait ?? delay)(500);
378
+ }
379
+ }
380
+ else {
381
+ await required(context, "systemctl", ["--user", "daemon-reload"], "installed");
382
+ await required(context, "systemctl", ["--user", "enable", `${name}.service`], "installed");
383
+ await required(context, "systemctl", ["--user", "restart", `${name}.service`], "started");
384
+ }
385
+ return Object.freeze({ name, platform: context.platform, definition, settingsFile });
386
+ }
387
+ export async function serviceInstalled(context) {
388
+ if (context.platform === "windows") {
389
+ const result = await context.run(windowsTool(context, "schtasks.exe"), ["/Query", "/TN", serviceName(context)]);
390
+ return result.code === 0 && result.missing !== true;
391
+ }
392
+ try {
393
+ await stat(serviceDefinitionPath(context));
394
+ return true;
395
+ }
396
+ catch {
397
+ return false;
398
+ }
399
+ }
400
+ /** Stops the running service without removing it. Returns false when it is not installed. */
401
+ export async function stopService(context) {
402
+ if (!(await serviceInstalled(context)))
403
+ return false;
404
+ const name = serviceName(context);
405
+ if (context.platform === "windows") {
406
+ // Ending the task ends conhost; the observer notices and stops itself.
407
+ await context.run(windowsTool(context, "schtasks.exe"), ["/End", "/TN", name]);
408
+ // The minute trigger would start it again; keep it off until started.
409
+ await context.run(windowsTool(context, "schtasks.exe"), ["/Change", "/TN", name, "/DISABLE"]);
410
+ }
411
+ else if (context.platform === "macos") {
412
+ // KeepAlive would restart a stopped job; unloading stops it for good.
413
+ await context.run("launchctl", ["bootout", `gui/${context.user}/${name}`]);
414
+ }
415
+ else {
416
+ await context.run("systemctl", ["--user", "stop", `${name}.service`]);
417
+ }
418
+ return true;
419
+ }
420
+ /** Starts the service again after `stopService`. */
421
+ export async function startService(context) {
422
+ const name = serviceName(context);
423
+ if (context.platform === "windows") {
424
+ await required(context, windowsTool(context, "schtasks.exe"), ["/Change", "/TN", name, "/ENABLE"], "started");
425
+ await required(context, windowsTool(context, "schtasks.exe"), ["/Run", "/TN", name], "started");
426
+ }
427
+ else if (context.platform === "macos") {
428
+ await required(context, "launchctl", ["bootstrap", `gui/${context.user}`, serviceDefinitionPath(context)], "started");
429
+ }
430
+ else {
431
+ await required(context, "systemctl", ["--user", "start", `${name}.service`], "started");
432
+ }
433
+ }
434
+ /** Stops and removes the service and its settings file. Returns false when it was not installed. */
435
+ export async function uninstallService(context) {
436
+ const installed = await serviceInstalled(context);
437
+ const name = serviceName(context);
438
+ if (installed) {
439
+ if (context.platform === "windows") {
440
+ await context.run(windowsTool(context, "schtasks.exe"), ["/End", "/TN", name]);
441
+ await required(context, windowsTool(context, "schtasks.exe"), ["/Delete", "/TN", name, "/F"], "removed");
442
+ }
443
+ else if (context.platform === "macos") {
444
+ await context.run("launchctl", ["bootout", `gui/${context.user}/${name}`]);
445
+ await unlink(serviceDefinitionPath(context)).catch(() => undefined);
446
+ }
447
+ else {
448
+ await context.run("systemctl", ["--user", "disable", "--now", `${name}.service`]);
449
+ await unlink(serviceDefinitionPath(context)).catch(() => undefined);
450
+ await context.run("systemctl", ["--user", "daemon-reload"]);
451
+ }
452
+ }
453
+ await rm(serviceSettingsPath(context.dataDirectory), { force: true });
454
+ return installed;
455
+ }
456
+ /** Runs a program with execFile: no shell, no window, a time limit. */
457
+ export const runCommand = async (command, args) => await new Promise((resolvePromise) => {
458
+ execFile(command, [...args], { windowsHide: true, timeout: 30_000, encoding: "utf8", maxBuffer: 1 << 20 }, (error, stdout, stderr) => {
459
+ if (error === null) {
460
+ resolvePromise({ code: 0, stdout, stderr });
461
+ return;
462
+ }
463
+ const code = error.code;
464
+ resolvePromise({
465
+ code: typeof error.code === "number" ? error.code : 1,
466
+ stdout: stdout ?? "",
467
+ stderr: stderr ?? "",
468
+ ...(code === "ENOENT" ? { missing: true } : {}),
469
+ });
470
+ });
471
+ });
472
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"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"}
@@ -3,12 +3,16 @@ import { type ObserverConfig } from "./config.js";
3
3
  import { type ActionPolicyPersistence } from "./action-policy.js";
4
4
  import { type CredentialStore } from "./credential-store.js";
5
5
  import type { BoundedEventQueue, QueueMetrics } from "./event-queue.js";
6
+ import { type SpoolRestoreNotice } from "./event-spool.js";
6
7
  import { type AgentInventory } from "./generated/phigon/v1/identity_pb.js";
7
8
  import { type HistorySyncCommand, type HistorySyncResult } from "./generated/phigon/v1/history_sync_pb.js";
8
9
  import { type CollectionPolicy } from "./generated/phigon/v1/policy_pb.js";
9
10
  import { type EventEnvelope } from "./generated/phigon/v1/telemetry_pb.js";
11
+ import type { ServerClock } from "./server-clock.js";
10
12
  import { StreamStateStore } from "./stream-state.js";
11
13
  type StreamStatePersistence = Pick<StreamStateStore, "load" | "save">;
14
+ /** How often an unchanged checkpoint is saved again while connected. */
15
+ export declare const streamStateRefreshMs: number;
12
16
  export type ObserverStreamMetrics = Readonly<{
13
17
  reconnects: number;
14
18
  acknowledgements: number;
@@ -29,18 +33,32 @@ export type StreamClientOptions = Readonly<{
29
33
  onAcknowledgement?: (sequence: bigint) => void | Promise<void>;
30
34
  actionExecutor?: ActionExecutor;
31
35
  onHistorySync?: (command: HistorySyncCommand) => Promise<HistorySyncResult>;
36
+ /** Learns the server's time from the timestamps on its replies. */
37
+ serverClock?: ServerClock;
32
38
  handshakeTimeoutMs?: number;
39
+ /** How often an unchanged checkpoint is saved again; tests shorten it. */
40
+ stateRefreshMs?: number;
33
41
  responseTimeoutMs?: number;
42
+ /** This observer's version, sent with every heartbeat. */
43
+ observerVersion?: string;
34
44
  }>;
35
45
  export declare class ObserverStreamClient {
36
46
  #private;
37
47
  constructor(options: StreamClientOptions);
38
48
  enqueue(event: EventEnvelope, coalesceKey?: string): void;
49
+ /**
50
+ * Writes the events queued so far to the durable spool. The spool groups
51
+ * its writes, so a source checkpoint may move past an event only after
52
+ * this returns. Throws when the spool cannot be written.
53
+ */
54
+ flush(): void;
39
55
  updateInventory(inventory: AgentInventory): void;
40
56
  waitUntilReady(signal?: AbortSignal): Promise<bigint>;
41
57
  run(signal: AbortSignal): Promise<void>;
42
58
  metrics(): ObserverStreamMetrics;
43
59
  }
60
+ /** A plain sentence for the log; it names no activity content. */
61
+ export declare function describeSpoolRestore(notice: SpoolRestoreNotice): string;
44
62
  export declare function sanitizeEventForPolicy(event: EventEnvelope, policy: CollectionPolicy): EventEnvelope;
45
63
  export {};
46
64
  //# sourceMappingURL=stream-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-client.d.ts","sourceRoot":"","sources":["../../src/stream-client.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAgC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAOhF,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAExE,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,0CAA0C,CAAC;AAWlD,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,oCAAoC,CAAC;AAK5C,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,KAAK,sBAAsB,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAOtE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,wBAAwB,EAAE,MAAM,CAAC;IACjC,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC,CAAC;AAEH,sDAAsD;AACtD,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,mBAAmB,EAAE,SAAS,GAAG,UAAU,CAAC,CAAC;AAE/E,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,MAAM,EAAE,cAAc,CAAC;IACvB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,UAAU,CAAC,EAAE,sBAAsB,CAAC;IACpC,KAAK,CAAC,EAAE,iBAAiB,CAAC,aAAa,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IAC5C,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,CACd,oBAAoB,EAAE,MAAM,EAC5B,kBAAkB,EAAE,MAAM,KACvB,IAAI,CAAC;IACV,iBAAiB,CAAC,EAAE,CAClB,QAAQ,EAAE,MAAM,KACb,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC,CAAC;AAEH,qBAAa,oBAAoB;;gBA+BnB,OAAO,EAAE,mBAAmB;IA2BxC,OAAO,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAWzD,eAAe,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI;IAK1C,cAAc,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBrD,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B7C,OAAO,IAAI,qBAAqB;CAulBjC;AA0FD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,gBAAgB,GACvB,aAAa,CA2If"}
1
+ {"version":3,"file":"stream-client.d.ts","sourceRoot":"","sources":["../../src/stream-client.ts"],"names":[],"mappings":"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"}