@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
package/dist/src/pair.js
CHANGED
|
@@ -1,25 +1,141 @@
|
|
|
1
1
|
import { arch, hostname, platform } from "node:os";
|
|
2
|
-
import { FileCredentialStore, } from "./credential-store.js";
|
|
3
|
-
import {
|
|
2
|
+
import { FileCredentialStore, credentialFileName, } from "./credential-store.js";
|
|
3
|
+
import { retirePairingState } from "./event-spool.js";
|
|
4
|
+
import { installationFileName, loadOrCreateInstallationID } from "./installation.js";
|
|
5
|
+
import { InstanceLock } from "./instance-lock.js";
|
|
4
6
|
export const OBSERVER_CONSENT_POLICY_VERSION = "observer-policy-v1";
|
|
5
7
|
export async function pairMachine(options) {
|
|
6
8
|
const code = options.code.trim();
|
|
7
9
|
if (code.length === 0) {
|
|
8
10
|
throw new Error("Pairing code is required.");
|
|
9
11
|
}
|
|
10
|
-
const installationID = await loadOrCreateInstallationID(options.config.dataDirectory);
|
|
11
12
|
if (options.config.observabilityProfile === "full" &&
|
|
12
13
|
options.consentProfile !== "full") {
|
|
13
14
|
throw new Error("The configured full observability profile requires full-content consent.");
|
|
14
15
|
}
|
|
15
16
|
const endpoint = new URL("/v1/pairing/exchange", options.config.controlPlaneUrl);
|
|
16
17
|
const fetcher = options.fetcher ?? fetch;
|
|
18
|
+
const connected = await connectMachine({
|
|
19
|
+
config: options.config,
|
|
20
|
+
endpoint,
|
|
21
|
+
fetcher,
|
|
22
|
+
...(options.credentialStore === undefined ? {} : { credentialStore: options.credentialStore }),
|
|
23
|
+
exchange: (installationID, existingCredential) => exchangePairing(fetcher, endpoint, {
|
|
24
|
+
code,
|
|
25
|
+
installation_id: installationID,
|
|
26
|
+
display_name: options.displayName?.trim() || hostname(),
|
|
27
|
+
hostname: hostname(),
|
|
28
|
+
operating_system: normalizedOperatingSystem(),
|
|
29
|
+
architecture: arch(),
|
|
30
|
+
consent: {
|
|
31
|
+
granted: true,
|
|
32
|
+
profile: options.consentProfile,
|
|
33
|
+
policy_version: OBSERVER_CONSENT_POLICY_VERSION,
|
|
34
|
+
},
|
|
35
|
+
...(existingCredential === undefined ? {} : { existing_credential: existingCredential }),
|
|
36
|
+
}),
|
|
37
|
+
evidence: (_paired, at) => ({
|
|
38
|
+
consentProfile: options.consentProfile,
|
|
39
|
+
consentPolicyVersion: OBSERVER_CONSENT_POLICY_VERSION,
|
|
40
|
+
consentedAt: at,
|
|
41
|
+
consentSource: "owner",
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
return connected.result;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Connects this computer with a code, keeping its machine when the server
|
|
48
|
+
* still accepts its stored key: pairing again, or enrolling, renews consent
|
|
49
|
+
* and keeps the same machine, so its queued activity stays deliverable.
|
|
50
|
+
* When the server no longer accepts the key, the computer connects as a
|
|
51
|
+
* new machine and its old queue moves aside.
|
|
52
|
+
*/
|
|
53
|
+
export async function connectMachine(options) {
|
|
54
|
+
const dataDirectory = options.config.dataDirectory;
|
|
55
|
+
const installationID = await loadOrCreateInstallationID(dataDirectory);
|
|
17
56
|
const credentialStore = options.credentialStore ??
|
|
18
|
-
new FileCredentialStore(
|
|
57
|
+
new FileCredentialStore(dataDirectory);
|
|
19
58
|
const previous = await credentialStore.load();
|
|
20
|
-
if (previous !== null && previous.controlPlaneOrigin !== endpoint.origin) {
|
|
59
|
+
if (previous !== null && previous.controlPlaneOrigin !== options.endpoint.origin) {
|
|
21
60
|
throw new Error("The stored machine belongs to a different control plane. Use a separate data directory to pair another workspace.");
|
|
22
61
|
}
|
|
62
|
+
let paired;
|
|
63
|
+
if (previous !== null) {
|
|
64
|
+
const renewal = await options.exchange(installationID, previous.credential);
|
|
65
|
+
if ("paired" in renewal) {
|
|
66
|
+
paired = renewal.paired;
|
|
67
|
+
}
|
|
68
|
+
else if (!renewal.credentialRejected) {
|
|
69
|
+
throw renewal.error;
|
|
70
|
+
}
|
|
71
|
+
else if (await credentialStillAccepted(options.fetcher, options.config.controlPlaneUrl, previous.credential)) {
|
|
72
|
+
// The exchange also refuses a key that is valid in another workspace.
|
|
73
|
+
throw new Error("This computer is paired with another workspace on this server. Use a separate data directory to pair another workspace.");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
let lock;
|
|
77
|
+
try {
|
|
78
|
+
if (paired === undefined || !sameMachine(previous, paired)) {
|
|
79
|
+
// A new machine. Its queue, stream cursor and credential start empty;
|
|
80
|
+
// the observer must not be using the old ones while they move.
|
|
81
|
+
lock = await InstanceLock.acquire(dataDirectory);
|
|
82
|
+
// The old credential goes with its queue: it is the only key that can
|
|
83
|
+
// decrypt it. Once it is gone, a retry after a lost response pairs
|
|
84
|
+
// without it, and the server answers with the same new machine.
|
|
85
|
+
//
|
|
86
|
+
// A key the server no longer accepts also retires its installation ID:
|
|
87
|
+
// a server can still hold that ID for the deleted machine, and the
|
|
88
|
+
// built-in SQLite server refuses to pair it again. A new ID pairs
|
|
89
|
+
// cleanly everywhere.
|
|
90
|
+
const replacing = paired === undefined && previous !== null;
|
|
91
|
+
retirePairingState(dataDirectory, previous?.machineId, [
|
|
92
|
+
credentialFileName,
|
|
93
|
+
...(replacing ? [installationFileName] : []),
|
|
94
|
+
]);
|
|
95
|
+
if (paired === undefined) {
|
|
96
|
+
const freshInstallationID = replacing
|
|
97
|
+
? await loadOrCreateInstallationID(dataDirectory)
|
|
98
|
+
: installationID;
|
|
99
|
+
const fresh = await options.exchange(freshInstallationID);
|
|
100
|
+
if (!("paired" in fresh))
|
|
101
|
+
throw fresh.error;
|
|
102
|
+
paired = fresh.paired;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const pairedAt = new Date().toISOString();
|
|
106
|
+
await credentialStore.save({
|
|
107
|
+
machineId: paired.machine.id,
|
|
108
|
+
tenantId: paired.machine.tenant_id,
|
|
109
|
+
credential: paired.credential,
|
|
110
|
+
controlPlaneOrigin: options.config.controlPlaneUrl.origin,
|
|
111
|
+
grpcOrigin: options.config.grpcUrl.origin,
|
|
112
|
+
createdAt: pairedAt,
|
|
113
|
+
...options.evidence(paired, pairedAt),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
await lock?.release();
|
|
118
|
+
}
|
|
119
|
+
const replaced = previous !== null && previous.machineId !== paired.machine.id;
|
|
120
|
+
return Object.freeze({
|
|
121
|
+
paired,
|
|
122
|
+
result: Object.freeze({
|
|
123
|
+
machineId: paired.machine.id,
|
|
124
|
+
displayName: paired.machine.display_name,
|
|
125
|
+
state: paired.machine.state,
|
|
126
|
+
controlPlaneOrigin: options.config.controlPlaneUrl.origin,
|
|
127
|
+
credentialStored: true,
|
|
128
|
+
...(replaced ? { replacedMachineId: previous.machineId } : {}),
|
|
129
|
+
}),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function sameMachine(previous, paired) {
|
|
133
|
+
return previous !== null &&
|
|
134
|
+
previous.machineId === paired.machine.id &&
|
|
135
|
+
previous.tenantId === paired.machine.tenant_id &&
|
|
136
|
+
previous.credential === paired.credential;
|
|
137
|
+
}
|
|
138
|
+
async function exchangePairing(fetcher, endpoint, body) {
|
|
23
139
|
let response;
|
|
24
140
|
try {
|
|
25
141
|
response = await fetcher(endpoint, {
|
|
@@ -28,20 +144,7 @@ export async function pairMachine(options) {
|
|
|
28
144
|
"Content-Type": "application/json",
|
|
29
145
|
Accept: "application/json",
|
|
30
146
|
},
|
|
31
|
-
body: JSON.stringify(
|
|
32
|
-
code,
|
|
33
|
-
...(previous === null ? {} : { existing_credential: previous.credential }),
|
|
34
|
-
installation_id: installationID,
|
|
35
|
-
display_name: options.displayName?.trim() || hostname(),
|
|
36
|
-
hostname: hostname(),
|
|
37
|
-
operating_system: normalizedOperatingSystem(),
|
|
38
|
-
architecture: arch(),
|
|
39
|
-
consent: {
|
|
40
|
-
granted: true,
|
|
41
|
-
profile: options.consentProfile,
|
|
42
|
-
policy_version: OBSERVER_CONSENT_POLICY_VERSION,
|
|
43
|
-
},
|
|
44
|
-
}),
|
|
147
|
+
body: JSON.stringify(body),
|
|
45
148
|
redirect: "error",
|
|
46
149
|
signal: AbortSignal.timeout(10_000),
|
|
47
150
|
});
|
|
@@ -53,7 +156,11 @@ export async function pairMachine(options) {
|
|
|
53
156
|
throw new Error(`Could not reach ${endpoint.origin}. Check your internet connection and try again.`);
|
|
54
157
|
}
|
|
55
158
|
if (!response.ok) {
|
|
56
|
-
|
|
159
|
+
const failure = await apiError(response);
|
|
160
|
+
return {
|
|
161
|
+
error: new Error(failure.message ?? `Pairing failed with HTTP ${response.status}.`),
|
|
162
|
+
credentialRejected: credentialRejected(response.status, failure),
|
|
163
|
+
};
|
|
57
164
|
}
|
|
58
165
|
let value;
|
|
59
166
|
try {
|
|
@@ -64,67 +171,98 @@ export async function pairMachine(options) {
|
|
|
64
171
|
// print fragments. The server supports retries for this installation.
|
|
65
172
|
throw new Error("The pairing response was incomplete or invalid. Retry with the same code before it expires; keep the existing data directory.");
|
|
66
173
|
}
|
|
67
|
-
|
|
68
|
-
const pairedAt = new Date().toISOString();
|
|
69
|
-
await credentialStore.save({
|
|
70
|
-
machineId: paired.machine.id,
|
|
71
|
-
tenantId: paired.machine.tenant_id,
|
|
72
|
-
credential: paired.credential,
|
|
73
|
-
controlPlaneOrigin: options.config.controlPlaneUrl.origin,
|
|
74
|
-
grpcOrigin: options.config.grpcUrl.origin,
|
|
75
|
-
createdAt: pairedAt,
|
|
76
|
-
consentProfile: options.consentProfile,
|
|
77
|
-
consentPolicyVersion: OBSERVER_CONSENT_POLICY_VERSION,
|
|
78
|
-
consentedAt: pairedAt,
|
|
79
|
-
});
|
|
80
|
-
return Object.freeze({
|
|
81
|
-
machineId: paired.machine.id,
|
|
82
|
-
displayName: paired.machine.display_name,
|
|
83
|
-
state: paired.machine.state,
|
|
84
|
-
controlPlaneOrigin: options.config.controlPlaneUrl.origin,
|
|
85
|
-
credentialStored: true,
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
function parsePairingResponse(value) {
|
|
89
|
-
if (typeof value !== "object" ||
|
|
90
|
-
value === null ||
|
|
91
|
-
!("credential" in value) ||
|
|
92
|
-
typeof value.credential !== "string" ||
|
|
93
|
-
!value.credential.startsWith("phg_m_") ||
|
|
94
|
-
!("machine" in value) ||
|
|
95
|
-
typeof value.machine !== "object" ||
|
|
96
|
-
value.machine === null ||
|
|
97
|
-
!("id" in value.machine) ||
|
|
98
|
-
typeof value.machine.id !== "string" ||
|
|
99
|
-
!("tenant_id" in value.machine) ||
|
|
100
|
-
typeof value.machine.tenant_id !== "string" ||
|
|
101
|
-
!("display_name" in value.machine) ||
|
|
102
|
-
typeof value.machine.display_name !== "string" ||
|
|
103
|
-
!("state" in value.machine) ||
|
|
104
|
-
typeof value.machine.state !== "string") {
|
|
174
|
+
if (!isConnectedMachine(value)) {
|
|
105
175
|
throw new Error("Control plane returned an invalid pairing response.");
|
|
106
176
|
}
|
|
107
|
-
return value;
|
|
177
|
+
return { paired: value };
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Whether a failed exchange refused the stored key. The server answers a
|
|
181
|
+
* key it no longer accepts with HTTP 400 and "machine credential is
|
|
182
|
+
* invalid".
|
|
183
|
+
*/
|
|
184
|
+
export function credentialRejected(status, failure) {
|
|
185
|
+
return failure.code === "invalid_credential" ||
|
|
186
|
+
(status === 400 &&
|
|
187
|
+
/^machine credential is (?:invalid|revoked)\b/iu.test(failure.message ?? ""));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Whether a server still accepts a stored key. Only a key the server
|
|
191
|
+
* itself calls invalid or revoked, because an administrator removed the
|
|
192
|
+
* computer or revoked the key, may be set aside for a new pairing.
|
|
193
|
+
*/
|
|
194
|
+
async function credentialStillAccepted(fetcher, controlPlaneUrl, credential) {
|
|
195
|
+
const endpoint = new URL("/v1/machine/heartbeat", controlPlaneUrl);
|
|
196
|
+
let response;
|
|
197
|
+
try {
|
|
198
|
+
response = await fetcher(endpoint, {
|
|
199
|
+
method: "POST",
|
|
200
|
+
headers: {
|
|
201
|
+
Authorization: `Bearer ${credential}`,
|
|
202
|
+
Accept: "application/json",
|
|
203
|
+
},
|
|
204
|
+
redirect: "error",
|
|
205
|
+
signal: AbortSignal.timeout(10_000),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
throw new Error(`Could not reach ${endpoint.origin} to check this computer's earlier pairing. Check your internet connection and try again.`);
|
|
210
|
+
}
|
|
211
|
+
if (response.ok) {
|
|
212
|
+
await response.body?.cancel();
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
if (response.status === 401 &&
|
|
216
|
+
(await apiError(response)).code === "invalid_credential") {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
throw new Error(`Could not check this computer's earlier pairing (HTTP ${response.status}). Try again.`);
|
|
220
|
+
}
|
|
221
|
+
/** A response with a machine and a machine credential. */
|
|
222
|
+
export function isConnectedMachine(value) {
|
|
223
|
+
return typeof value === "object" &&
|
|
224
|
+
value !== null &&
|
|
225
|
+
"credential" in value &&
|
|
226
|
+
typeof value.credential === "string" &&
|
|
227
|
+
value.credential.startsWith("phg_m_") &&
|
|
228
|
+
"machine" in value &&
|
|
229
|
+
typeof value.machine === "object" &&
|
|
230
|
+
value.machine !== null &&
|
|
231
|
+
"id" in value.machine &&
|
|
232
|
+
typeof value.machine.id === "string" &&
|
|
233
|
+
"tenant_id" in value.machine &&
|
|
234
|
+
typeof value.machine.tenant_id === "string" &&
|
|
235
|
+
"display_name" in value.machine &&
|
|
236
|
+
typeof value.machine.display_name === "string" &&
|
|
237
|
+
"state" in value.machine &&
|
|
238
|
+
typeof value.machine.state === "string";
|
|
108
239
|
}
|
|
109
|
-
|
|
240
|
+
/** The `{ error: { code, message } }` body of a failed control-plane call. */
|
|
241
|
+
export async function apiError(response) {
|
|
110
242
|
try {
|
|
111
243
|
const value = await response.json();
|
|
112
244
|
if (typeof value === "object" &&
|
|
113
245
|
value !== null &&
|
|
114
246
|
"error" in value &&
|
|
115
247
|
typeof value.error === "object" &&
|
|
116
|
-
value.error !== null
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
248
|
+
value.error !== null) {
|
|
249
|
+
const error = value.error;
|
|
250
|
+
return {
|
|
251
|
+
...("code" in error && typeof error.code === "string"
|
|
252
|
+
? { code: error.code }
|
|
253
|
+
: {}),
|
|
254
|
+
...("message" in error && typeof error.message === "string"
|
|
255
|
+
? { message: error.message }
|
|
256
|
+
: {}),
|
|
257
|
+
};
|
|
120
258
|
}
|
|
121
259
|
}
|
|
122
260
|
catch {
|
|
123
261
|
// The status code still provides an actionable, non-sensitive failure.
|
|
124
262
|
}
|
|
125
|
-
return
|
|
263
|
+
return {};
|
|
126
264
|
}
|
|
127
|
-
function normalizedOperatingSystem() {
|
|
265
|
+
export function normalizedOperatingSystem() {
|
|
128
266
|
const value = platform();
|
|
129
267
|
if (value === "darwin")
|
|
130
268
|
return "macos";
|
package/dist/src/pair.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pair.js","sourceRoot":"","sources":["../../src/pair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EACL,mBAAmB,
|
|
1
|
+
{"version":3,"file":"pair.js","sourceRoot":"","sources":["../../src/pair.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The current account's SID from whoami. A name built from USERDOMAIN and
|
|
3
|
+
* USERNAME does not resolve for every account: services that run as
|
|
4
|
+
* LocalSystem or a virtual account see names icacls cannot look up.
|
|
5
|
+
*/
|
|
6
|
+
export declare function currentUserSID(): string | undefined;
|
|
1
7
|
/** Restrict an existing directory to its owner on every platform. */
|
|
2
8
|
export declare function makeDirectoryPrivate(path: string): Promise<void>;
|
|
3
9
|
export declare function makeDirectoryPrivateSync(path: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private-directory.d.ts","sourceRoot":"","sources":["../../src/private-directory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"private-directory.d.ts","sourceRoot":"","sources":["../../src/private-directory.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CAkBnD;AAuBD,qEAAqE;AACrE,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAG3D"}
|
|
@@ -1,16 +1,47 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { chmodSync } from "node:fs";
|
|
3
3
|
import { chmod } from "node:fs/promises";
|
|
4
|
-
import { resolve } from "node:path";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
5
|
// chmod only changes the read-only flag on Windows, so the credential store and
|
|
6
6
|
// event spool would otherwise rely on the profile folder's default ACL. Owner
|
|
7
7
|
// and SYSTEM keep access; files created inside inherit the restriction.
|
|
8
8
|
const restricted = new Set();
|
|
9
|
+
// The account this process runs as, by security identifier: null when
|
|
10
|
+
// Windows would not say.
|
|
11
|
+
let processUserSID;
|
|
12
|
+
/**
|
|
13
|
+
* The current account's SID from whoami. A name built from USERDOMAIN and
|
|
14
|
+
* USERNAME does not resolve for every account: services that run as
|
|
15
|
+
* LocalSystem or a virtual account see names icacls cannot look up.
|
|
16
|
+
*/
|
|
17
|
+
export function currentUserSID() {
|
|
18
|
+
if (processUserSID === undefined) {
|
|
19
|
+
processUserSID = null;
|
|
20
|
+
try {
|
|
21
|
+
// By full path: Git for Windows puts another whoami on PATH.
|
|
22
|
+
const whoami = join(process.env["SystemRoot"] ?? "C:\\Windows", "System32", "whoami.exe");
|
|
23
|
+
const output = execFileSync(whoami, ["/user", "/fo", "csv", "/nh"], {
|
|
24
|
+
encoding: "utf8",
|
|
25
|
+
windowsHide: true,
|
|
26
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
27
|
+
timeout: 15_000,
|
|
28
|
+
});
|
|
29
|
+
processUserSID = /"(S-1-[0-9]+(?:-[0-9]+){1,15})"\s*$/u.exec(output.trim())?.[1] ?? null;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Fall back to the account name below.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return processUserSID ?? undefined;
|
|
36
|
+
}
|
|
9
37
|
function restrictWindowsDirectory(path) {
|
|
10
38
|
const key = resolve(path).toLowerCase();
|
|
11
39
|
if (restricted.has(key))
|
|
12
40
|
return;
|
|
13
|
-
const
|
|
41
|
+
const sid = currentUserSID();
|
|
42
|
+
const owner = sid === undefined
|
|
43
|
+
? `${process.env["USERDOMAIN"] ?? ""}\\${process.env["USERNAME"] ?? ""}`
|
|
44
|
+
: `*${sid}`;
|
|
14
45
|
try {
|
|
15
46
|
execFileSync("icacls", [resolve(path), "/inheritance:r", "/grant:r", `${owner}:(OI)(CI)F`, "/grant:r", "*S-1-5-18:(OI)(CI)F"], { windowsHide: true, stdio: "ignore", timeout: 15_000 });
|
|
16
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private-directory.js","sourceRoot":"","sources":["../../src/private-directory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"private-directory.js","sourceRoot":"","sources":["../../src/private-directory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Socket } from "node:net";
|
|
2
|
+
/**
|
|
3
|
+
* Corporate proxies. The observer's HTTPS calls (pairing, removal, update
|
|
4
|
+
* checks, Guardian and the doctor probe) use `fetch`, which ignores
|
|
5
|
+
* HTTPS_PROXY unless Node.js is told to read it, and the telemetry stream
|
|
6
|
+
* uses @grpc/grpc-js, which reads only the lowercase names. This module
|
|
7
|
+
* points both at the same proxy, using what Node.js offers natively.
|
|
8
|
+
*
|
|
9
|
+
* HTTPS goes through the proxy as a CONNECT tunnel, and TLS is negotiated
|
|
10
|
+
* with the server itself inside it, so the usual certificate checks,
|
|
11
|
+
* including an authority pinned for a company's own server, still apply.
|
|
12
|
+
*/
|
|
13
|
+
export type ProxySettings = Readonly<{
|
|
14
|
+
https?: URL;
|
|
15
|
+
http?: URL;
|
|
16
|
+
/** NO_PROXY as written: comma- or space-separated host names. */
|
|
17
|
+
noProxy: string;
|
|
18
|
+
}>;
|
|
19
|
+
/** Reads HTTPS_PROXY, HTTP_PROXY and NO_PROXY (either case) from `environment`. */
|
|
20
|
+
export declare function proxySettings(environment: NodeJS.ProcessEnv): ProxySettings;
|
|
21
|
+
/**
|
|
22
|
+
* The proxy `target` goes through, or undefined to connect directly. It
|
|
23
|
+
* follows Node.js: an entry matches its host and every host under it
|
|
24
|
+
* (`example.com`, `.example.com` and `*.example.com` all cover
|
|
25
|
+
* `a.example.com`), `*` matches everything, and `host:port` only that port.
|
|
26
|
+
*/
|
|
27
|
+
export declare function proxyForUrl(target: URL, settings: ProxySettings): URL | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* NO_PROXY in the form @grpc/grpc-js reads, which matches plain host name
|
|
30
|
+
* endings only: `*.example.com` and `.example.com` become `example.com`, and
|
|
31
|
+
* an entry for another port is left out because the stream cannot check
|
|
32
|
+
* ports.
|
|
33
|
+
*/
|
|
34
|
+
export declare function grpcNoProxy(noProxy: string, streamPort: number): string;
|
|
35
|
+
/** Whether NO_PROXY turns the proxy off for every host, which grpc-js cannot express. */
|
|
36
|
+
export declare function noProxyForAll(environment: NodeJS.ProcessEnv): boolean;
|
|
37
|
+
type SetGlobalProxy = (environment: NodeJS.ProcessEnv) => () => void;
|
|
38
|
+
export type ProxySetup = Readonly<{
|
|
39
|
+
/** Puts back the global agents and the variables changed for the stream. */
|
|
40
|
+
restore: () => void;
|
|
41
|
+
/** A plain sentence to show when part of the setup could not be applied. */
|
|
42
|
+
notice?: string;
|
|
43
|
+
}>;
|
|
44
|
+
export type ProxySetupOptions = Readonly<{
|
|
45
|
+
/** `http.setGlobalProxyFromEnv`, Node.js 24.14 and newer. */
|
|
46
|
+
setGlobalProxyFromEnv?: SetGlobalProxy | undefined;
|
|
47
|
+
/** The environment @grpc/grpc-js reads: process.env. */
|
|
48
|
+
processEnvironment?: NodeJS.ProcessEnv;
|
|
49
|
+
/** Whether Node.js already applied the proxy variables when it started. */
|
|
50
|
+
startedWithEnvProxy?: boolean;
|
|
51
|
+
nodeVersion?: string;
|
|
52
|
+
/** The telemetry endpoint, to keep NO_PROXY port entries for it. */
|
|
53
|
+
streamUrl?: URL;
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Sends `fetch` (and `http`/`https` requests) through the proxy that
|
|
57
|
+
* `environment` names, and gives the telemetry stream the same proxy and
|
|
58
|
+
* NO_PROXY list. Does nothing when no proxy is set.
|
|
59
|
+
*/
|
|
60
|
+
export declare function useProxyFromEnvironment(environment: NodeJS.ProcessEnv, options?: ProxySetupOptions): ProxySetup;
|
|
61
|
+
/**
|
|
62
|
+
* Opens a CONNECT tunnel through `proxy` to `host:port`, for a raw TLS
|
|
63
|
+
* connection that `fetch` does not cover. Messages name the proxy by host
|
|
64
|
+
* only, never with its credentials.
|
|
65
|
+
*/
|
|
66
|
+
export declare function connectThroughProxy(proxy: URL, host: string, port: number, timeoutMs?: number): Promise<Socket>;
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC;IACnC,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAuCH,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,UAAU,GAAG,aAAa,CAQ3E;AAaD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,aAAa,GAAG,GAAG,GAAG,SAAS,CAYjF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAKvE;AAED,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAGrE;AAED,KAAK,cAAc,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,UAAU,KAAK,MAAM,IAAI,CAAC;AAErE,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,4EAA4E;IAC5E,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,6DAA6D;IAC7D,qBAAqB,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnD,wDAAwD;IACxD,kBAAkB,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACvC,2EAA2E;IAC3E,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB,CAAC,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,CAAC,UAAU,EAC9B,OAAO,GAAE,iBAAsB,GAC9B,UAAU,CA0DZ;AAOD;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,GAAG,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,SAAS,GACjB,OAAO,CAAC,MAAM,CAAC,CAoCjB"}
|