@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.
- package/README.md +194 -11
- package/dist/bin/guardian-runner-darwin-amd64 +0 -0
- package/dist/bin/guardian-runner-darwin-arm64 +0 -0
- package/dist/bin/guardian-runner-linux-amd64 +0 -0
- package/dist/bin/guardian-runner-linux-arm64 +0 -0
- package/dist/bin/guardian-runner-windows-amd64.exe +0 -0
- package/dist/bin/guardian-runner-windows-arm64.exe +0 -0
- package/dist/src/abortable-delay.d.ts +10 -0
- package/dist/src/abortable-delay.d.ts.map +1 -0
- package/dist/src/abortable-delay.js +21 -0
- package/dist/src/abortable-delay.js.map +1 -0
- package/dist/src/activity/adapters/claude.d.ts.map +1 -1
- package/dist/src/activity/adapters/claude.js +9 -1
- package/dist/src/activity/adapters/claude.js.map +1 -1
- package/dist/src/activity/adapters/openai-compatible.d.ts.map +1 -1
- package/dist/src/activity/adapters/openai-compatible.js +9 -1
- package/dist/src/activity/adapters/openai-compatible.js.map +1 -1
- package/dist/src/activity/collector.d.ts +31 -1
- package/dist/src/activity/collector.d.ts.map +1 -1
- package/dist/src/activity/collector.js +337 -77
- package/dist/src/activity/collector.js.map +1 -1
- package/dist/src/activity/ingest.d.ts +9 -0
- package/dist/src/activity/ingest.d.ts.map +1 -1
- package/dist/src/activity/ingest.js +92 -3
- package/dist/src/activity/ingest.js.map +1 -1
- package/dist/src/activity/json-document-source.d.ts +15 -0
- package/dist/src/activity/json-document-source.d.ts.map +1 -1
- package/dist/src/activity/json-document-source.js +19 -2
- package/dist/src/activity/json-document-source.js.map +1 -1
- package/dist/src/activity/native-capabilities.d.ts.map +1 -1
- package/dist/src/activity/native-capabilities.js +8 -12
- package/dist/src/activity/native-capabilities.js.map +1 -1
- package/dist/src/activity/opencode-sqlite-source.js +1 -0
- package/dist/src/activity/opencode-sqlite-source.js.map +1 -1
- package/dist/src/activity/source-reader.d.ts +44 -3
- package/dist/src/activity/source-reader.d.ts.map +1 -1
- package/dist/src/activity/source-reader.js +325 -86
- package/dist/src/activity/source-reader.js.map +1 -1
- package/dist/src/agent-action-executor.d.ts +5 -0
- package/dist/src/agent-action-executor.d.ts.map +1 -1
- package/dist/src/agent-action-executor.js +9 -6
- package/dist/src/agent-action-executor.js.map +1 -1
- package/dist/src/atomic-replace.d.ts +7 -0
- package/dist/src/atomic-replace.d.ts.map +1 -1
- package/dist/src/atomic-replace.js +28 -3
- package/dist/src/atomic-replace.js.map +1 -1
- package/dist/src/bridge-journal.d.ts +32 -0
- package/dist/src/bridge-journal.d.ts.map +1 -0
- package/dist/src/bridge-journal.js +113 -0
- package/dist/src/bridge-journal.js.map +1 -0
- package/dist/src/cli.d.ts +7 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +490 -43
- package/dist/src/cli.js.map +1 -1
- package/dist/src/collection-notice.d.ts +34 -0
- package/dist/src/collection-notice.d.ts.map +1 -0
- package/dist/src/collection-notice.js +73 -0
- package/dist/src/collection-notice.js.map +1 -0
- package/dist/src/config.d.ts +26 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +88 -33
- package/dist/src/config.js.map +1 -1
- package/dist/src/content-redaction.d.ts +17 -1
- package/dist/src/content-redaction.d.ts.map +1 -1
- package/dist/src/content-redaction.js +44 -3
- package/dist/src/content-redaction.js.map +1 -1
- package/dist/src/credential-store.d.ts +20 -1
- package/dist/src/credential-store.d.ts.map +1 -1
- package/dist/src/credential-store.js +27 -3
- package/dist/src/credential-store.js.map +1 -1
- package/dist/src/discovery/engine.d.ts.map +1 -1
- package/dist/src/discovery/engine.js +1 -11
- package/dist/src/discovery/engine.js.map +1 -1
- package/dist/src/doctor-check.d.ts +51 -0
- package/dist/src/doctor-check.d.ts.map +1 -0
- package/dist/src/doctor-check.js +174 -0
- package/dist/src/doctor-check.js.map +1 -0
- package/dist/src/enroll.d.ts +86 -0
- package/dist/src/enroll.d.ts.map +1 -0
- package/dist/src/enroll.js +245 -0
- package/dist/src/enroll.js.map +1 -0
- package/dist/src/entry.d.ts +3 -0
- package/dist/src/entry.d.ts.map +1 -0
- package/dist/src/entry.js +14 -0
- package/dist/src/entry.js.map +1 -0
- package/dist/src/event-queue.d.ts +13 -1
- package/dist/src/event-queue.d.ts.map +1 -1
- package/dist/src/event-queue.js +50 -5
- package/dist/src/event-queue.js.map +1 -1
- package/dist/src/event-spool.d.ts +61 -3
- package/dist/src/event-spool.d.ts.map +1 -1
- package/dist/src/event-spool.js +290 -41
- package/dist/src/event-spool.js.map +1 -1
- package/dist/src/generated/phigon/v1/identity_pb.d.ts +7 -0
- package/dist/src/generated/phigon/v1/identity_pb.d.ts.map +1 -1
- package/dist/src/generated/phigon/v1/identity_pb.js +1 -1
- package/dist/src/generated/phigon/v1/identity_pb.js.map +1 -1
- package/dist/src/guardian-decision-journal.d.ts.map +1 -1
- package/dist/src/guardian-decision-journal.js +4 -20
- package/dist/src/guardian-decision-journal.js.map +1 -1
- package/dist/src/guardian-managed-exec.js +6 -19
- package/dist/src/guardian-managed-exec.js.map +1 -1
- package/dist/src/guardian-process-monitor.d.ts +1 -0
- package/dist/src/guardian-process-monitor.d.ts.map +1 -1
- package/dist/src/guardian-process-monitor.js +74 -26
- package/dist/src/guardian-process-monitor.js.map +1 -1
- package/dist/src/health.d.ts +19 -1
- package/dist/src/health.d.ts.map +1 -1
- package/dist/src/health.js +22 -1
- package/dist/src/health.js.map +1 -1
- package/dist/src/historical-identity-store.d.ts +8 -1
- package/dist/src/historical-identity-store.d.ts.map +1 -1
- package/dist/src/historical-identity-store.js +26 -9
- package/dist/src/historical-identity-store.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/installation.d.ts +2 -0
- package/dist/src/installation.d.ts.map +1 -1
- package/dist/src/installation.js +3 -1
- package/dist/src/installation.js.map +1 -1
- package/dist/src/instance-lock.d.ts +45 -0
- package/dist/src/instance-lock.d.ts.map +1 -0
- package/dist/src/instance-lock.js +243 -0
- package/dist/src/instance-lock.js.map +1 -0
- package/dist/src/machine-command-executor.d.ts +2 -2
- package/dist/src/machine-command-executor.d.ts.map +1 -1
- package/dist/src/machine-command-executor.js +7 -20
- package/dist/src/machine-command-executor.js.map +1 -1
- package/dist/src/node-version.d.ts +8 -0
- package/dist/src/node-version.d.ts.map +1 -0
- package/dist/src/node-version.js +17 -0
- package/dist/src/node-version.js.map +1 -0
- package/dist/src/observer-log.d.ts +50 -0
- package/dist/src/observer-log.d.ts.map +1 -0
- package/dist/src/observer-log.js +141 -0
- package/dist/src/observer-log.js.map +1 -0
- package/dist/src/pair.d.ts +68 -1
- package/dist/src/pair.d.ts.map +1 -1
- package/dist/src/pair.js +204 -66
- package/dist/src/pair.js.map +1 -1
- package/dist/src/private-directory.d.ts +6 -0
- package/dist/src/private-directory.d.ts.map +1 -1
- package/dist/src/private-directory.js +33 -2
- package/dist/src/private-directory.js.map +1 -1
- package/dist/src/proxy.d.ts +68 -0
- package/dist/src/proxy.d.ts.map +1 -0
- package/dist/src/proxy.js +209 -0
- package/dist/src/proxy.js.map +1 -0
- package/dist/src/purge.d.ts +17 -0
- package/dist/src/purge.d.ts.map +1 -0
- package/dist/src/purge.js +84 -0
- package/dist/src/purge.js.map +1 -0
- package/dist/src/remove-machine.d.ts +5 -1
- package/dist/src/remove-machine.d.ts.map +1 -1
- package/dist/src/remove-machine.js +28 -14
- package/dist/src/remove-machine.js.map +1 -1
- package/dist/src/server-authority.d.ts +5 -2
- package/dist/src/server-authority.d.ts.map +1 -1
- package/dist/src/server-authority.js +10 -6
- package/dist/src/server-authority.js.map +1 -1
- package/dist/src/server-clock.d.ts +32 -0
- package/dist/src/server-clock.d.ts.map +1 -0
- package/dist/src/server-clock.js +72 -0
- package/dist/src/server-clock.js.map +1 -0
- package/dist/src/service-command.d.ts +20 -0
- package/dist/src/service-command.d.ts.map +1 -0
- package/dist/src/service-command.js +136 -0
- package/dist/src/service-command.js.map +1 -0
- package/dist/src/service.d.ts +98 -0
- package/dist/src/service.d.ts.map +1 -0
- package/dist/src/service.js +472 -0
- package/dist/src/service.js.map +1 -0
- package/dist/src/stream-client.d.ts +18 -0
- package/dist/src/stream-client.d.ts.map +1 -1
- package/dist/src/stream-client.js +91 -16
- package/dist/src/stream-client.js.map +1 -1
- package/dist/src/stream-state.d.ts +2 -0
- package/dist/src/stream-state.d.ts.map +1 -1
- package/dist/src/stream-state.js +3 -1
- package/dist/src/stream-state.js.map +1 -1
- package/dist/src/user-notices.d.ts +11 -0
- package/dist/src/user-notices.d.ts.map +1 -1
- package/dist/src/user-notices.js +24 -0
- package/dist/src/user-notices.js.map +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server's idea of the time, estimated from the times it stamps on the
|
|
3
|
+
* stream (acknowledgements and policies). Remote commands carry an expiry in
|
|
4
|
+
* server time, so judging it by a computer clock that is a few minutes off
|
|
5
|
+
* would reject or extend every command.
|
|
6
|
+
*
|
|
7
|
+
* Each sample is the server's stamp minus the local time it arrived, which
|
|
8
|
+
* is the true offset less the one-way network delay: well under a second,
|
|
9
|
+
* against command windows of minutes. The estimate is the median of recent
|
|
10
|
+
* samples, so one odd stamp does not move it, and it is bounded so a broken
|
|
11
|
+
* stamp cannot move the clock arbitrarily far.
|
|
12
|
+
*/
|
|
13
|
+
export class ServerClock {
|
|
14
|
+
#now;
|
|
15
|
+
#maxCorrectionMs;
|
|
16
|
+
#largeSkewMs;
|
|
17
|
+
#onLargeSkew;
|
|
18
|
+
#samples = [];
|
|
19
|
+
#offsetMs = 0;
|
|
20
|
+
// The offset last reported as large, so a steady skew is reported once.
|
|
21
|
+
#reportedOffsetMs;
|
|
22
|
+
constructor(options = {}) {
|
|
23
|
+
this.#now = options.now ?? Date.now;
|
|
24
|
+
this.#maxCorrectionMs = options.maxCorrectionMs ?? maxCorrectionMs;
|
|
25
|
+
this.#largeSkewMs = options.largeSkewMs ?? largeSkewMs;
|
|
26
|
+
this.#onLargeSkew = options.onLargeSkew ?? (() => undefined);
|
|
27
|
+
}
|
|
28
|
+
/** Records a server timestamp that arrived just now. */
|
|
29
|
+
observe(serverTime) {
|
|
30
|
+
const sample = serverTime.getTime() - this.#now();
|
|
31
|
+
if (!Number.isFinite(sample))
|
|
32
|
+
return;
|
|
33
|
+
this.#samples.push(sample);
|
|
34
|
+
if (this.#samples.length > retainedSamples)
|
|
35
|
+
this.#samples.shift();
|
|
36
|
+
const sorted = [...this.#samples].sort((left, right) => left - right);
|
|
37
|
+
const median = sorted[Math.floor(sorted.length / 2)] ?? 0;
|
|
38
|
+
this.#offsetMs = Math.max(-this.#maxCorrectionMs, Math.min(this.#maxCorrectionMs, median));
|
|
39
|
+
const large = Math.abs(median) >= this.#largeSkewMs;
|
|
40
|
+
if (!large) {
|
|
41
|
+
this.#reportedOffsetMs = undefined;
|
|
42
|
+
}
|
|
43
|
+
else if (this.#reportedOffsetMs === undefined ||
|
|
44
|
+
Math.abs(median - this.#reportedOffsetMs) >= this.#largeSkewMs) {
|
|
45
|
+
this.#reportedOffsetMs = median;
|
|
46
|
+
this.#onLargeSkew(median);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** How far the server's clock is ahead of this computer's, as applied. */
|
|
50
|
+
offsetMs() {
|
|
51
|
+
return this.#offsetMs;
|
|
52
|
+
}
|
|
53
|
+
/** The current time on the server's clock, in epoch milliseconds. */
|
|
54
|
+
now() {
|
|
55
|
+
return this.#now() + this.#offsetMs;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** A plain-English description of a clock skew, for status messages. */
|
|
59
|
+
export function describeClockSkew(offsetMs) {
|
|
60
|
+
const seconds = Math.round(Math.abs(offsetMs) / 1_000);
|
|
61
|
+
const amount = seconds >= 120
|
|
62
|
+
? `${Math.round(seconds / 60)} minutes`
|
|
63
|
+
: `${seconds} seconds`;
|
|
64
|
+
return `This computer's clock is ${amount} ${offsetMs > 0 ? "behind" : "ahead of"} the workspace server. ` +
|
|
65
|
+
"Remote commands are timed by the server's clock; correct the computer's clock to keep other tools accurate.";
|
|
66
|
+
}
|
|
67
|
+
const retainedSamples = 9;
|
|
68
|
+
// Covers a clock set to the wrong time zone, as on a computer that also
|
|
69
|
+
// starts another operating system, without trusting a wildly wrong stamp.
|
|
70
|
+
const maxCorrectionMs = 24 * 3_600_000;
|
|
71
|
+
const largeSkewMs = 60_000;
|
|
72
|
+
//# sourceMappingURL=server-clock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-clock.js","sourceRoot":"","sources":["../../src/server-clock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ObserverConfig } from "./config.js";
|
|
2
|
+
import { type CommandRunner, type ServiceContext } from "./service.js";
|
|
3
|
+
export type ServiceDependencies = Readonly<{
|
|
4
|
+
/** Runs schtasks, launchctl or systemctl; tests replace it. */
|
|
5
|
+
serviceRunner?: CommandRunner;
|
|
6
|
+
/** The operating system to install for; tests replace it. */
|
|
7
|
+
platform?: NodeJS.Platform;
|
|
8
|
+
/** How long to wait for a stopping observer to let go of its data directory. */
|
|
9
|
+
stopTimeoutMs?: number;
|
|
10
|
+
/** The home folder a LaunchAgent or user unit goes under; tests replace it. */
|
|
11
|
+
homeDirectory?: string;
|
|
12
|
+
}>;
|
|
13
|
+
type Output = Readonly<{
|
|
14
|
+
stdout: (value: string) => void;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function serviceContext(config: ObserverConfig, environment: NodeJS.ProcessEnv, dependencies?: ServiceDependencies): ServiceContext;
|
|
17
|
+
/** `service install | uninstall | status`. */
|
|
18
|
+
export declare function runServiceCommand(flags: readonly string[], config: ObserverConfig, environment: NodeJS.ProcessEnv, output: Output, json: boolean, dependencies?: ServiceDependencies): Promise<number>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=service-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-command.d.ts","sourceRoot":"","sources":["../../src/service-command.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAMhF,OAAO,EASL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,+DAA+D;IAC/D,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC;AAEH,KAAK,MAAM,GAAG,QAAQ,CAAC;IAAE,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAAC,CAAC;AAE5D,wBAAgB,cAAc,CAC5B,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,CAAC,UAAU,EAC9B,YAAY,GAAE,mBAAwB,GACrC,cAAc,CAuBhB;AAwCD,8CAA8C;AAC9C,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,CAAC,UAAU,EAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,YAAY,GAAE,mBAAwB,GACrC,OAAO,CAAC,MAAM,CAAC,CAgEjB"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { homedir, userInfo } from "node:os";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
5
|
+
import { contentOutsideProfileMessage } from "./config.js";
|
|
6
|
+
import { FileCredentialStore } from "./credential-store.js";
|
|
7
|
+
import { InstanceLock } from "./instance-lock.js";
|
|
8
|
+
import { logFilePath } from "./observer-log.js";
|
|
9
|
+
import { OBSERVER_CONSENT_POLICY_VERSION } from "./pair.js";
|
|
10
|
+
import { currentUserSID } from "./private-directory.js";
|
|
11
|
+
import { installService, runCommand, serviceDefinitionPath, serviceInstalled, serviceName, servicePlatform, serviceSettings, uninstallService, } from "./service.js";
|
|
12
|
+
export function serviceContext(config, environment, dependencies = {}) {
|
|
13
|
+
const platform = servicePlatform(dependencies.platform ?? process.platform);
|
|
14
|
+
if (platform === undefined) {
|
|
15
|
+
throw new Error("Background services are available on Windows, macOS and Linux. Keep phigon-observer run running another way.");
|
|
16
|
+
}
|
|
17
|
+
const dataDirectory = resolve(config.dataDirectory);
|
|
18
|
+
const fallback = resolve(join(homedir(), ".phigon", "observer"));
|
|
19
|
+
const same = (a, b) => platform === "windows" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
20
|
+
const account = userInfo();
|
|
21
|
+
return Object.freeze({
|
|
22
|
+
platform,
|
|
23
|
+
dataDirectory,
|
|
24
|
+
defaultDataDirectory: same(dataDirectory, fallback),
|
|
25
|
+
nodePath: process.execPath,
|
|
26
|
+
entryPath: fileURLToPath(new URL("./entry.js", import.meta.url)),
|
|
27
|
+
homeDirectory: dependencies.homeDirectory ?? homedir(),
|
|
28
|
+
user: platform === "windows"
|
|
29
|
+
? (currentUserSID() ?? `${environment["USERDOMAIN"] ?? process.env["USERDOMAIN"] ?? ""}\\${account.username}`)
|
|
30
|
+
: String(account.uid),
|
|
31
|
+
configHome: environment["XDG_CONFIG_HOME"]?.trim() || undefined,
|
|
32
|
+
systemRoot: process.env["SystemRoot"] ?? process.env["SYSTEMROOT"],
|
|
33
|
+
run: dependencies.serviceRunner ?? runCommand,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/** Why collection cannot start on this computer, or undefined when it can. */
|
|
37
|
+
async function installRefusal(config) {
|
|
38
|
+
const credential = await new FileCredentialStore(config.dataDirectory).load();
|
|
39
|
+
if (credential === null) {
|
|
40
|
+
return "This computer is not paired, so a background service would have nothing to collect. Pair it with the command from Connect machine, then run service install again.";
|
|
41
|
+
}
|
|
42
|
+
if (credential.controlPlaneOrigin !== config.controlPlaneUrl.origin) {
|
|
43
|
+
return `This computer is paired with ${credential.controlPlaneOrigin}, but the observer is set up for ${config.controlPlaneUrl.origin}. Remove the other control plane setting and try again.`;
|
|
44
|
+
}
|
|
45
|
+
if (credential.consentPolicyVersion !== OBSERVER_CONSENT_POLICY_VERSION || credential.consentProfile === undefined) {
|
|
46
|
+
return "The computer owner's consent is missing or out of date. Pair again with --consent-profile metadata or full, then run service install again.";
|
|
47
|
+
}
|
|
48
|
+
if (config.observabilityProfile === "full" && credential.consentProfile !== "full") {
|
|
49
|
+
return "Full-content collection is outside the consented metadata profile. Install the service with --profile metadata, or pair again with full-activity consent.";
|
|
50
|
+
}
|
|
51
|
+
if (config.contentSettingsOutsideProfile.length > 0) {
|
|
52
|
+
return contentOutsideProfileMessage(config.contentSettingsOutsideProfile);
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
async function waitUntilStopped(dataDirectory, timeoutMs) {
|
|
57
|
+
const deadline = Date.now() + timeoutMs;
|
|
58
|
+
while (Date.now() < deadline) {
|
|
59
|
+
if (!(await InstanceLock.inspect(dataDirectory)).running)
|
|
60
|
+
return true;
|
|
61
|
+
await delay(250);
|
|
62
|
+
}
|
|
63
|
+
return !(await InstanceLock.inspect(dataDirectory)).running;
|
|
64
|
+
}
|
|
65
|
+
function restartNote(context) {
|
|
66
|
+
return context.platform === "windows"
|
|
67
|
+
? "It starts when you sign in, and again within a minute if it stops."
|
|
68
|
+
: context.platform === "macos"
|
|
69
|
+
? "It starts when you sign in, and launchd starts it again if it stops."
|
|
70
|
+
: "It starts when you sign in, and systemd restarts it if it fails.";
|
|
71
|
+
}
|
|
72
|
+
/** `service install | uninstall | status`. */
|
|
73
|
+
export async function runServiceCommand(flags, config, environment, output, json, dependencies = {}) {
|
|
74
|
+
const subcommand = flags[0];
|
|
75
|
+
if (subcommand !== "install" && subcommand !== "uninstall" && subcommand !== "status") {
|
|
76
|
+
throw new Error("service requires one of: install, uninstall, or status. Run phigon-observer help for usage.");
|
|
77
|
+
}
|
|
78
|
+
const context = serviceContext(config, environment, dependencies);
|
|
79
|
+
const name = serviceName(context);
|
|
80
|
+
const logFile = logFilePath(context.dataDirectory);
|
|
81
|
+
const definition = serviceDefinitionPath(context) ?? name;
|
|
82
|
+
if (subcommand === "status") {
|
|
83
|
+
const installed = await serviceInstalled(context);
|
|
84
|
+
const running = (await InstanceLock.inspect(context.dataDirectory)).running;
|
|
85
|
+
const state = !installed ? "not_installed" : running ? "running" : "stopped";
|
|
86
|
+
output.stdout(json
|
|
87
|
+
? `${JSON.stringify({ state, installed, running, name, platform: context.platform, definition, dataDirectory: context.dataDirectory, logFile }, null, 2)}\n`
|
|
88
|
+
: [
|
|
89
|
+
`Background service: ${!installed ? "not installed" : running ? "installed and running" : "installed and stopped"}`,
|
|
90
|
+
`Name: ${name}`,
|
|
91
|
+
...(installed ? [`Log: ${logFile}`] : []),
|
|
92
|
+
...(!installed && running ? ["An observer started by hand is running with this data directory."] : []),
|
|
93
|
+
"",
|
|
94
|
+
].join("\n"));
|
|
95
|
+
return 0;
|
|
96
|
+
}
|
|
97
|
+
if (subcommand === "uninstall") {
|
|
98
|
+
const removed = await uninstallService(context);
|
|
99
|
+
const stopped = removed ? await waitUntilStopped(context.dataDirectory, dependencies.stopTimeoutMs ?? 15_000) : true;
|
|
100
|
+
output.stdout(json
|
|
101
|
+
? `${JSON.stringify({ status: removed ? "removed" : "not_installed", name, platform: context.platform, observerStopped: stopped }, null, 2)}\n`
|
|
102
|
+
: [
|
|
103
|
+
removed ? `Background service removed: ${name}.` : "The background service was not installed.",
|
|
104
|
+
...(removed && !stopped ? ["The observer is still stopping; it exits within a few seconds."] : []),
|
|
105
|
+
"",
|
|
106
|
+
].join("\n"));
|
|
107
|
+
return 0;
|
|
108
|
+
}
|
|
109
|
+
const refusal = await installRefusal(config);
|
|
110
|
+
if (refusal !== undefined)
|
|
111
|
+
throw new Error(refusal);
|
|
112
|
+
const settings = { ...serviceSettings(environment), PHIGON_OBSERVABILITY_PROFILE: config.observabilityProfile };
|
|
113
|
+
const alreadyRunning = (await InstanceLock.inspect(context.dataDirectory)).running;
|
|
114
|
+
const result = await installService(context, settings);
|
|
115
|
+
const notes = [
|
|
116
|
+
restartNote(context),
|
|
117
|
+
...(alreadyRunning
|
|
118
|
+
? ["An observer is already running with this data directory. The service takes over when it stops."]
|
|
119
|
+
: []),
|
|
120
|
+
...(context.platform === "linux"
|
|
121
|
+
? [`To keep collecting while ${userInfo().username} is signed out, an administrator can run: loginctl enable-linger ${userInfo().username}`]
|
|
122
|
+
: []),
|
|
123
|
+
];
|
|
124
|
+
output.stdout(json
|
|
125
|
+
? `${JSON.stringify({ status: "installed", name, platform: context.platform, definition: result.definition, settingsFile: result.settingsFile, logFile, profile: config.observabilityProfile, notes }, null, 2)}\n`
|
|
126
|
+
: [
|
|
127
|
+
`Background service installed: ${name}`,
|
|
128
|
+
`Collection profile: ${config.observabilityProfile}`,
|
|
129
|
+
...notes,
|
|
130
|
+
`Settings: ${result.settingsFile}`,
|
|
131
|
+
`Log: ${logFile}`,
|
|
132
|
+
"",
|
|
133
|
+
].join("\n"));
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=service-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-command.js","sourceRoot":"","sources":["../../src/service-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The observer as a background service of the signed-in user: a Task
|
|
3
|
+
* Scheduler task on Windows, a LaunchAgent on macOS and a systemd user unit
|
|
4
|
+
* on Linux. It runs as that user, not as SYSTEM or root, because it reads
|
|
5
|
+
* that user's agent files. The definition holds only the Node.js binary,
|
|
6
|
+
* the observer's entry point and the path of the settings file in the data
|
|
7
|
+
* directory; settings and the machine key stay in the data directory.
|
|
8
|
+
*/
|
|
9
|
+
export type ServicePlatform = "windows" | "macos" | "linux";
|
|
10
|
+
export type CommandResult = Readonly<{
|
|
11
|
+
code: number;
|
|
12
|
+
stdout: string;
|
|
13
|
+
stderr: string;
|
|
14
|
+
/** The program does not exist on this computer. */
|
|
15
|
+
missing?: boolean;
|
|
16
|
+
}>;
|
|
17
|
+
/** Runs a program without a shell. Tests replace it; nothing is installed. */
|
|
18
|
+
export type CommandRunner = (command: string, args: readonly string[]) => Promise<CommandResult>;
|
|
19
|
+
export declare const serviceSettingsFileName = "service-settings.json";
|
|
20
|
+
export type ServiceContext = Readonly<{
|
|
21
|
+
platform: ServicePlatform;
|
|
22
|
+
/** Absolute data directory the service runs with. */
|
|
23
|
+
dataDirectory: string;
|
|
24
|
+
/** Whether that is the default ~/.phigon/observer, which keeps the plain name. */
|
|
25
|
+
defaultDataDirectory: boolean;
|
|
26
|
+
/** The Node.js binary and observer entry point that ran `service install`. */
|
|
27
|
+
nodePath: string;
|
|
28
|
+
entryPath: string;
|
|
29
|
+
homeDirectory: string;
|
|
30
|
+
/** Windows: the account's SID or DOMAIN\user. macOS: the numeric uid. */
|
|
31
|
+
user: string;
|
|
32
|
+
/** Linux: $XDG_CONFIG_HOME when it is set. */
|
|
33
|
+
configHome?: string | undefined;
|
|
34
|
+
/** Windows: %SystemRoot%. */
|
|
35
|
+
systemRoot?: string | undefined;
|
|
36
|
+
run: CommandRunner;
|
|
37
|
+
now?: () => Date;
|
|
38
|
+
/** Waits between retries; tests make it instant. */
|
|
39
|
+
wait?: (ms: number) => Promise<void>;
|
|
40
|
+
}>;
|
|
41
|
+
export declare function servicePlatform(platform: NodeJS.Platform): ServicePlatform | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* The service's name. One observer runs per data directory, so a directory
|
|
44
|
+
* other than the default gets its own service, named with a short digest
|
|
45
|
+
* of its path.
|
|
46
|
+
*/
|
|
47
|
+
export declare function serviceName(context: Pick<ServiceContext, "platform" | "dataDirectory" | "defaultDataDirectory">): string;
|
|
48
|
+
export declare function serviceSettingsPath(dataDirectory: string): string;
|
|
49
|
+
/** Where the definition file lives; Windows keeps it in Task Scheduler. */
|
|
50
|
+
export declare function serviceDefinitionPath(context: ServiceContext): string | undefined;
|
|
51
|
+
/** The command the service runs. */
|
|
52
|
+
export declare function serviceCommand(context: ServiceContext): readonly string[];
|
|
53
|
+
/**
|
|
54
|
+
* Task Scheduler XML. The task starts at sign-in and is retried every minute
|
|
55
|
+
* (a running copy is left alone), so an observer that stops is started again
|
|
56
|
+
* within a minute. conhost --headless keeps a console window from opening;
|
|
57
|
+
* it does not pass on the exit code, so the minute trigger, not the failure
|
|
58
|
+
* setting, is what restarts it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function windowsTaskXml(context: ServiceContext): string;
|
|
61
|
+
/** A LaunchAgent that starts at sign-in and is started again if it stops. */
|
|
62
|
+
export declare function launchAgentPlist(context: ServiceContext): string;
|
|
63
|
+
/** A systemd user unit, restarted when it fails. */
|
|
64
|
+
export declare function systemdUserUnit(context: ServiceContext): string;
|
|
65
|
+
/**
|
|
66
|
+
* The settings from `environment` that the service needs to behave like
|
|
67
|
+
* this terminal: PHIGON_* settings (never a token or password), PATH for
|
|
68
|
+
* finding agents, proxy and certificate settings, and the folders some
|
|
69
|
+
* agents keep their records in. The data directory is where the file is.
|
|
70
|
+
*/
|
|
71
|
+
export declare function serviceSettings(environment: NodeJS.ProcessEnv): Record<string, string>;
|
|
72
|
+
export declare function writeServiceSettings(dataDirectory: string, settings: Readonly<Record<string, string>>): Promise<string>;
|
|
73
|
+
/** Reads and checks the settings file; anything unexpected is refused. */
|
|
74
|
+
export declare function readServiceSettings(path: string): Promise<Record<string, string>>;
|
|
75
|
+
export declare class ServiceError extends Error {
|
|
76
|
+
}
|
|
77
|
+
export type ServiceInstallResult = Readonly<{
|
|
78
|
+
name: string;
|
|
79
|
+
platform: ServicePlatform;
|
|
80
|
+
/** The definition file, or the Task Scheduler task name on Windows. */
|
|
81
|
+
definition: string;
|
|
82
|
+
settingsFile: string;
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* Installs the service, replacing an earlier definition of the same name,
|
|
86
|
+
* and starts it. The caller checks pairing and consent first.
|
|
87
|
+
*/
|
|
88
|
+
export declare function installService(context: ServiceContext, settings: Readonly<Record<string, string>>): Promise<ServiceInstallResult>;
|
|
89
|
+
export declare function serviceInstalled(context: ServiceContext): Promise<boolean>;
|
|
90
|
+
/** Stops the running service without removing it. Returns false when it is not installed. */
|
|
91
|
+
export declare function stopService(context: ServiceContext): Promise<boolean>;
|
|
92
|
+
/** Starts the service again after `stopService`. */
|
|
93
|
+
export declare function startService(context: ServiceContext): Promise<void>;
|
|
94
|
+
/** Stops and removes the service and its settings file. Returns false when it was not installed. */
|
|
95
|
+
export declare function uninstallService(context: ServiceContext): Promise<boolean>;
|
|
96
|
+
/** Runs a program with execFile: no shell, no window, a time limit. */
|
|
97
|
+
export declare const runCommand: CommandRunner;
|
|
98
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"AAQA;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC,CAAC;AAEH,8EAA8E;AAC9E,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAEjG,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAK/D,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,QAAQ,EAAE,eAAe,CAAC;IAC1B,qDAAqD;IACrD,aAAa,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,oBAAoB,EAAE,OAAO,CAAC;IAC9B,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,GAAG,EAAE,aAAa,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,oDAAoD;IACpD,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC,CAAC,CAAC;AAEH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,eAAe,GAAG,SAAS,CAKtF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,eAAe,GAAG,sBAAsB,CAAC,GAAG,MAAM,CAQxH;AAED,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,2EAA2E;AAC3E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAWjF;AAYD,oCAAoC;AACpC,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,MAAM,EAAE,CAYzE;AAaD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAkE9D;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CA+BhE;AAED,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAoB/D;AA0BD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWtF;AAED,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB7H;AAED,0EAA0E;AAC1E,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAoCvF;AAKD,qBAAa,YAAa,SAAQ,KAAK;CAAG;AA+B1C,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC;IAC1B,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAEH;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACzC,OAAO,CAAC,oBAAoB,CAAC,CA4C/B;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAWhF;AAED,6FAA6F;AAC7F,wBAAsB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAe3E;AAED,oDAAoD;AACpD,wBAAsB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzE;AAED,oGAAoG;AACpG,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBhF;AAED,uEAAuE;AACvE,eAAO,MAAM,UAAU,EAAE,aAerB,CAAC"}
|