@elpapi42/pi-fleet 0.1.0-beta.2 → 0.1.0-beta.5
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/CHANGELOG.md +41 -0
- package/README.md +2 -2
- package/dist/cli-meta.json +6 -6
- package/dist/cli.mjs +159 -54
- package/dist/cli.mjs.map +3 -3
- package/dist/installer-meta.json +6 -6
- package/dist/installer.mjs +158 -53
- package/dist/installer.mjs.map +3 -3
- package/dist/runtime-manifest.json +28 -31
- package/dist/runtime-meta.json +22 -11
- package/dist/runtime.mjs +97 -17
- package/dist/runtime.mjs.map +3 -3
- package/package.json +1 -1
package/dist/installer-meta.json
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"format": "esm"
|
|
44
44
|
},
|
|
45
45
|
"src/platform/install/tree-integrity.ts": {
|
|
46
|
-
"bytes":
|
|
46
|
+
"bytes": 2529,
|
|
47
47
|
"imports": [
|
|
48
48
|
{
|
|
49
49
|
"path": "node:crypto",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"format": "esm"
|
|
65
65
|
},
|
|
66
66
|
"src/platform/install/runtime-release.ts": {
|
|
67
|
-
"bytes":
|
|
67
|
+
"bytes": 15742,
|
|
68
68
|
"imports": [
|
|
69
69
|
{
|
|
70
70
|
"path": "node:crypto",
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
"imports": [],
|
|
153
153
|
"exports": [],
|
|
154
154
|
"inputs": {},
|
|
155
|
-
"bytes":
|
|
155
|
+
"bytes": 46947
|
|
156
156
|
},
|
|
157
157
|
"dist/installer.mjs": {
|
|
158
158
|
"imports": [
|
|
@@ -259,16 +259,16 @@
|
|
|
259
259
|
"bytesInOutput": 1889
|
|
260
260
|
},
|
|
261
261
|
"src/platform/install/runtime-release.ts": {
|
|
262
|
-
"bytesInOutput":
|
|
262
|
+
"bytesInOutput": 13667
|
|
263
263
|
},
|
|
264
264
|
"src/platform/install/tree-integrity.ts": {
|
|
265
|
-
"bytesInOutput":
|
|
265
|
+
"bytesInOutput": 2193
|
|
266
266
|
},
|
|
267
267
|
"src/platform/shared/paths.ts": {
|
|
268
268
|
"bytesInOutput": 1207
|
|
269
269
|
}
|
|
270
270
|
},
|
|
271
|
-
"bytes":
|
|
271
|
+
"bytes": 25294
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
}
|
package/dist/installer.mjs
CHANGED
|
@@ -156,12 +156,12 @@ async function atomicWrite(path, contents) {
|
|
|
156
156
|
|
|
157
157
|
// src/platform/install/runtime-release.ts
|
|
158
158
|
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
159
|
-
import { chmod as chmod2, cp, lstat as lstat2, mkdir as mkdir2, readFile as readFile3, rename as rename2, rm as rm2 } from "node:fs/promises";
|
|
159
|
+
import { chmod as chmod2, cp, lstat as lstat2, mkdir as mkdir2, readFile as readFile3, rename as rename2, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
|
|
160
160
|
import { join as join3, posix, resolve as resolve2, sep as sep2 } from "node:path";
|
|
161
161
|
|
|
162
162
|
// src/platform/install/tree-integrity.ts
|
|
163
163
|
import { createHash } from "node:crypto";
|
|
164
|
-
import { lstat, readFile as readFile2, readdir, stat } from "node:fs/promises";
|
|
164
|
+
import { lstat, readFile as readFile2, readdir, realpath, stat } from "node:fs/promises";
|
|
165
165
|
import { join as join2, relative, resolve, sep } from "node:path";
|
|
166
166
|
async function hashDirectoryTree(root, manifestPath) {
|
|
167
167
|
const resolvedRoot = resolve(root);
|
|
@@ -201,6 +201,14 @@ async function collectFiles(root, directory) {
|
|
|
201
201
|
if (!info.isFile()) {
|
|
202
202
|
throw new Error(`Runtime dependency tree contains an unsupported entry: ${absolutePath}`);
|
|
203
203
|
}
|
|
204
|
+
if (linkInfo.isSymbolicLink()) {
|
|
205
|
+
const target = await realpath(absolutePath);
|
|
206
|
+
if (target !== root && !target.startsWith(`${root}${sep}`)) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`Runtime dependency tree contains an external file symlink: ${absolutePath}`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
204
212
|
const relativePath = relative(root, absolutePath).split(sep).join("/");
|
|
205
213
|
if (relativePath.length === 0 || relativePath.startsWith("../")) {
|
|
206
214
|
throw new Error(`Runtime dependency path escapes its root: ${absolutePath}`);
|
|
@@ -219,19 +227,33 @@ var requiredRuntimeArtifacts = /* @__PURE__ */ new Set([
|
|
|
219
227
|
"dist/runtime.mjs",
|
|
220
228
|
"dist/sqlite-worker.mjs"
|
|
221
229
|
]);
|
|
230
|
+
var dependencyTreePath = "node_modules";
|
|
222
231
|
async function materializeRuntime(options) {
|
|
223
232
|
const sourceRoot = resolve2(options.sourceRoot);
|
|
224
233
|
const manifestBytes = await readFile3(join3(sourceRoot, "dist", "runtime-manifest.json"));
|
|
225
|
-
const
|
|
226
|
-
|
|
234
|
+
const sourceManifest = await parseRuntimeManifest(manifestBytes, sourceRoot);
|
|
235
|
+
if (sourceManifest.closure !== void 0) {
|
|
236
|
+
await verifyRuntime(sourceRoot);
|
|
237
|
+
return sourceRoot;
|
|
238
|
+
}
|
|
239
|
+
await verifyRuntimeFiles(sourceRoot, sourceManifest);
|
|
240
|
+
await verifyDependencyIdentities(sourceRoot, sourceManifest.dependencies);
|
|
241
|
+
const sourceTreeRoot = resolveInside(sourceRoot, dependencyTreePath);
|
|
242
|
+
const sourceTreeBefore = await hashDirectoryTree(sourceTreeRoot, dependencyTreePath);
|
|
243
|
+
const sourceManifestSha256 = createHash2("sha256").update(manifestBytes).digest("hex");
|
|
244
|
+
const materializedManifest = {
|
|
245
|
+
...sourceManifest,
|
|
246
|
+
closure: { sourceManifestSha256, tree: sourceTreeBefore }
|
|
247
|
+
};
|
|
248
|
+
const materializedManifestBytes = serializeManifest(materializedManifest);
|
|
249
|
+
const closureHash = createHash2("sha256").update(sourceManifestSha256).update("\0").update(JSON.stringify(sourceTreeBefore)).digest("hex").slice(0, 16);
|
|
227
250
|
const applicationRoot = resolve2(options.applicationRoot);
|
|
228
251
|
await ensurePrivateDirectory(applicationRoot);
|
|
229
|
-
const manifestHash = createHash2("sha256").update(manifestBytes).digest("hex").slice(0, 16);
|
|
230
252
|
const releasesRoot = join3(applicationRoot, "releases");
|
|
231
253
|
await ensurePrivateDirectory(releasesRoot);
|
|
232
|
-
const destination = join3(releasesRoot, `${
|
|
254
|
+
const destination = join3(releasesRoot, `${sourceManifest.package.version}-${closureHash}`);
|
|
233
255
|
if (await pathExists(destination)) {
|
|
234
|
-
await
|
|
256
|
+
await verifyExpectedRuntime(destination, materializedManifest, materializedManifestBytes);
|
|
235
257
|
return destination;
|
|
236
258
|
}
|
|
237
259
|
const staging = join3(releasesRoot, `.staging-${randomUUID()}`);
|
|
@@ -241,36 +263,73 @@ async function materializeRuntime(options) {
|
|
|
241
263
|
recursive: true,
|
|
242
264
|
dereference: true
|
|
243
265
|
});
|
|
244
|
-
await cp(join3(sourceRoot, "bin"), join3(staging, "bin"), {
|
|
266
|
+
await cp(join3(sourceRoot, "bin"), join3(staging, "bin"), {
|
|
267
|
+
recursive: true,
|
|
268
|
+
dereference: true
|
|
269
|
+
});
|
|
245
270
|
await cp(join3(sourceRoot, "package.json"), join3(staging, "package.json"));
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
271
|
+
await cp(sourceTreeRoot, join3(staging, dependencyTreePath), {
|
|
272
|
+
recursive: true,
|
|
273
|
+
dereference: true
|
|
274
|
+
});
|
|
275
|
+
await options.hooks?.afterDependencyCopy?.();
|
|
276
|
+
const stagedTree = await hashDirectoryTree(
|
|
277
|
+
join3(staging, dependencyTreePath),
|
|
278
|
+
dependencyTreePath
|
|
279
|
+
);
|
|
280
|
+
assertSameTree(sourceTreeBefore, stagedTree, "copied dependency closure");
|
|
281
|
+
const sourceTreeAfter = await hashDirectoryTree(sourceTreeRoot, dependencyTreePath);
|
|
282
|
+
assertSameTree(sourceTreeBefore, sourceTreeAfter, "source dependency closure");
|
|
283
|
+
await writeFile2(join3(staging, "dist", "runtime-manifest.json"), materializedManifestBytes);
|
|
284
|
+
await verifyExpectedRuntime(staging, materializedManifest, materializedManifestBytes);
|
|
253
285
|
await chmod2(staging, 448);
|
|
254
286
|
try {
|
|
255
287
|
await rename2(staging, destination);
|
|
256
288
|
} catch (error) {
|
|
257
289
|
if (!isDestinationRace(error) || !await pathExists(destination)) throw error;
|
|
258
|
-
await
|
|
290
|
+
await verifyExpectedRuntime(destination, materializedManifest, materializedManifestBytes);
|
|
259
291
|
}
|
|
260
292
|
return destination;
|
|
261
293
|
} finally {
|
|
262
294
|
await rm2(staging, { recursive: true, force: true });
|
|
263
295
|
}
|
|
264
296
|
}
|
|
265
|
-
async function verifyRuntime(root
|
|
297
|
+
async function verifyRuntime(root) {
|
|
266
298
|
const resolvedRoot = resolve2(root);
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
299
|
+
const manifestBytes = await readFile3(join3(resolvedRoot, "dist", "runtime-manifest.json"));
|
|
300
|
+
const manifest = await parseRuntimeManifest(manifestBytes, resolvedRoot);
|
|
301
|
+
if (manifest.closure === void 0) {
|
|
302
|
+
throw new Error("Runtime release manifest is missing its materialized closure");
|
|
303
|
+
}
|
|
304
|
+
await verifyRuntimeFiles(resolvedRoot, manifest);
|
|
305
|
+
await verifyDependencyIdentities(resolvedRoot, manifest.dependencies);
|
|
306
|
+
const actualTree = await hashDirectoryTree(
|
|
307
|
+
resolveInside(resolvedRoot, dependencyTreePath),
|
|
308
|
+
dependencyTreePath
|
|
270
309
|
);
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
310
|
+
assertSameTree(manifest.closure.tree, actualTree, "materialized dependency closure");
|
|
311
|
+
}
|
|
312
|
+
async function verifyExpectedRuntime(root, expected, expectedBytes) {
|
|
313
|
+
const manifestPath = join3(root, "dist", "runtime-manifest.json");
|
|
314
|
+
const actualBytes = await readFile3(manifestPath);
|
|
315
|
+
if (!actualBytes.equals(expectedBytes)) {
|
|
316
|
+
throw new Error("Materialized runtime manifest does not match the expected closure");
|
|
317
|
+
}
|
|
318
|
+
const actual = await parseRuntimeManifest(actualBytes, root);
|
|
319
|
+
if (actual.closure === void 0 || expected.closure === void 0) {
|
|
320
|
+
throw new Error("Materialized runtime manifest is missing its closure");
|
|
321
|
+
}
|
|
322
|
+
await verifyRuntimeFiles(root, actual);
|
|
323
|
+
await verifyDependencyIdentities(root, actual.dependencies);
|
|
324
|
+
const actualTree = await hashDirectoryTree(
|
|
325
|
+
resolveInside(root, dependencyTreePath),
|
|
326
|
+
dependencyTreePath
|
|
327
|
+
);
|
|
328
|
+
assertSameTree(expected.closure.tree, actualTree, "materialized dependency closure");
|
|
329
|
+
}
|
|
330
|
+
async function verifyRuntimeFiles(root, manifest) {
|
|
331
|
+
for (const file of manifest.files) {
|
|
332
|
+
const path = resolveInside(root, file.path);
|
|
274
333
|
const info = await lstat2(path);
|
|
275
334
|
if (info.isSymbolicLink()) {
|
|
276
335
|
throw new Error(`Runtime artifact ${file.path} must not be a symbolic link`);
|
|
@@ -283,11 +342,27 @@ async function verifyRuntime(root, manifest) {
|
|
|
283
342
|
throw new Error(`Runtime artifact ${file.path} failed verification`);
|
|
284
343
|
}
|
|
285
344
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
345
|
+
}
|
|
346
|
+
async function verifyDependencyIdentities(root, dependencies) {
|
|
347
|
+
const nodeModules = resolveInside(root, dependencyTreePath);
|
|
348
|
+
const modulesInfo = await lstat2(nodeModules);
|
|
349
|
+
if (!modulesInfo.isDirectory() || modulesInfo.isSymbolicLink()) {
|
|
350
|
+
throw new Error("Runtime dependency closure must be a regular directory");
|
|
351
|
+
}
|
|
352
|
+
for (const dependency of dependencies) {
|
|
353
|
+
const packageRoot = resolveInside(root, dependency.path);
|
|
354
|
+
const packageInfo = await lstat2(packageRoot);
|
|
355
|
+
if (!packageInfo.isDirectory() || packageInfo.isSymbolicLink()) {
|
|
356
|
+
throw new Error(`Runtime dependency ${dependency.name} must be a regular directory`);
|
|
357
|
+
}
|
|
358
|
+
const packageJsonPath = join3(packageRoot, "package.json");
|
|
359
|
+
const packageJsonInfo = await lstat2(packageJsonPath);
|
|
360
|
+
if (!packageJsonInfo.isFile() || packageJsonInfo.isSymbolicLink()) {
|
|
361
|
+
throw new Error(`Runtime dependency ${dependency.name} has an unsafe package.json`);
|
|
362
|
+
}
|
|
363
|
+
const identity = await readPackageMetadata(packageRoot);
|
|
364
|
+
if (identity.name !== dependency.name || identity.version !== dependency.version) {
|
|
365
|
+
throw new Error(`Runtime dependency ${dependency.name} has an unexpected identity`);
|
|
291
366
|
}
|
|
292
367
|
}
|
|
293
368
|
}
|
|
@@ -302,17 +377,17 @@ async function parseRuntimeManifest(bytes, root) {
|
|
|
302
377
|
return candidate;
|
|
303
378
|
}
|
|
304
379
|
async function validateRuntimeManifest(candidate, root) {
|
|
305
|
-
if (!isRecord(candidate) || candidate.schemaVersion !==
|
|
380
|
+
if (!isRecord(candidate) || candidate.schemaVersion !== 3) {
|
|
306
381
|
throw new Error("Runtime manifest has an unsupported schema version");
|
|
307
382
|
}
|
|
308
|
-
if (!isRecord(candidate.package) || typeof candidate.package.name !== "string" || typeof candidate.package.version !== "string") {
|
|
383
|
+
if (!isRecord(candidate.package) || typeof candidate.package.name !== "string" || typeof candidate.package.version !== "string" || typeof candidate.managedPi !== "string") {
|
|
309
384
|
throw new Error("Runtime manifest has an invalid package identity");
|
|
310
385
|
}
|
|
311
|
-
const
|
|
312
|
-
if (candidate.package.name !==
|
|
386
|
+
const packageMetadata = await readPackageMetadata(root);
|
|
387
|
+
if (candidate.package.name !== packageMetadata.name || candidate.package.version !== packageMetadata.version) {
|
|
313
388
|
throw new Error("Runtime manifest package identity does not match package.json");
|
|
314
389
|
}
|
|
315
|
-
if (!Array.isArray(candidate.files) || !Array.isArray(candidate.
|
|
390
|
+
if (!Array.isArray(candidate.files) || !Array.isArray(candidate.dependencies)) {
|
|
316
391
|
throw new Error("Runtime manifest has invalid artifact lists");
|
|
317
392
|
}
|
|
318
393
|
const filePaths = /* @__PURE__ */ new Set();
|
|
@@ -320,8 +395,9 @@ async function validateRuntimeManifest(candidate, root) {
|
|
|
320
395
|
if (!isRecord(file) || !isManifestPath(file.path) || !isValidSize(file.bytes) || !isSha256(file.sha256)) {
|
|
321
396
|
throw new Error("Runtime manifest contains an invalid artifact");
|
|
322
397
|
}
|
|
323
|
-
if (filePaths.has(file.path))
|
|
398
|
+
if (filePaths.has(file.path)) {
|
|
324
399
|
throw new Error(`Runtime manifest has duplicate path ${file.path}`);
|
|
400
|
+
}
|
|
325
401
|
filePaths.add(file.path);
|
|
326
402
|
}
|
|
327
403
|
for (const required of requiredRuntimeArtifacts) {
|
|
@@ -329,37 +405,63 @@ async function validateRuntimeManifest(candidate, root) {
|
|
|
329
405
|
throw new Error(`Runtime manifest is missing required artifact ${required}`);
|
|
330
406
|
}
|
|
331
407
|
}
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
408
|
+
const dependencyPaths = /* @__PURE__ */ new Set();
|
|
409
|
+
const dependencyNames = /* @__PURE__ */ new Set();
|
|
410
|
+
for (const dependency of candidate.dependencies) {
|
|
411
|
+
if (!isRecord(dependency) || !isManifestPath(dependency.path) || typeof dependency.name !== "string" || dependency.name.length === 0 || typeof dependency.version !== "string" || dependency.version.length === 0 || dependency.path !== `node_modules/${dependency.name}`) {
|
|
412
|
+
throw new Error("Runtime manifest contains an invalid dependency declaration");
|
|
336
413
|
}
|
|
337
|
-
if (
|
|
338
|
-
throw new Error(`Runtime manifest has duplicate
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
414
|
+
if (dependencyPaths.has(dependency.path) || dependencyNames.has(dependency.name)) {
|
|
415
|
+
throw new Error(`Runtime manifest has duplicate dependency ${dependency.name}`);
|
|
416
|
+
}
|
|
417
|
+
dependencyPaths.add(dependency.path);
|
|
418
|
+
dependencyNames.add(dependency.name);
|
|
419
|
+
}
|
|
420
|
+
const expectedDependencies = packageMetadata.dependencies;
|
|
421
|
+
if (dependencyNames.size !== Object.keys(expectedDependencies).length || [...dependencyNames].some(
|
|
422
|
+
(name) => expectedDependencies[name] !== candidate.dependencies.find(
|
|
423
|
+
(dependency) => dependency.name === name
|
|
424
|
+
)?.version
|
|
425
|
+
)) {
|
|
426
|
+
throw new Error("Runtime manifest dependencies do not match package.json");
|
|
427
|
+
}
|
|
428
|
+
for (const filePath of filePaths) {
|
|
429
|
+
for (const dependencyPath of dependencyPaths) {
|
|
430
|
+
if (filePath === dependencyPath || filePath.startsWith(`${dependencyPath}/`) || dependencyPath.startsWith(`${filePath}/`)) {
|
|
431
|
+
throw new Error(`Runtime manifest has overlapping paths ${filePath} and ${dependencyPath}`);
|
|
348
432
|
}
|
|
349
433
|
}
|
|
350
434
|
}
|
|
435
|
+
if (candidate.closure !== void 0) {
|
|
436
|
+
if (!isRecord(candidate.closure) || !isSha256(candidate.closure.sourceManifestSha256) || !isTreeIntegrity(candidate.closure.tree) || candidate.closure.tree.path !== dependencyTreePath) {
|
|
437
|
+
throw new Error("Runtime manifest contains an invalid materialized closure");
|
|
438
|
+
}
|
|
439
|
+
}
|
|
351
440
|
}
|
|
352
|
-
async function
|
|
441
|
+
async function readPackageMetadata(root) {
|
|
353
442
|
let candidate;
|
|
354
443
|
try {
|
|
355
444
|
candidate = JSON.parse(await readFile3(join3(root, "package.json"), "utf8"));
|
|
356
445
|
} catch {
|
|
357
446
|
throw new Error("Runtime package.json is not valid JSON");
|
|
358
447
|
}
|
|
359
|
-
if (!isRecord(candidate) || typeof candidate.name !== "string" || typeof candidate.version !== "string") {
|
|
360
|
-
throw new Error("Runtime package.json has
|
|
448
|
+
if (!isRecord(candidate) || typeof candidate.name !== "string" || typeof candidate.version !== "string" || candidate.dependencies !== void 0 && !isRecord(candidate.dependencies) || isRecord(candidate.dependencies) && Object.values(candidate.dependencies).some((version) => typeof version !== "string")) {
|
|
449
|
+
throw new Error("Runtime package.json has invalid package metadata");
|
|
450
|
+
}
|
|
451
|
+
return {
|
|
452
|
+
name: candidate.name,
|
|
453
|
+
version: candidate.version,
|
|
454
|
+
dependencies: isRecord(candidate.dependencies) ? candidate.dependencies : {}
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
function serializeManifest(manifest) {
|
|
458
|
+
return Buffer.from(`${JSON.stringify(manifest, null, 2)}
|
|
459
|
+
`);
|
|
460
|
+
}
|
|
461
|
+
function assertSameTree(expected, actual, label) {
|
|
462
|
+
if (expected.path !== actual.path || expected.files !== actual.files || expected.bytes !== actual.bytes || expected.sha256 !== actual.sha256) {
|
|
463
|
+
throw new Error(`Runtime ${label} changed during materialization`);
|
|
361
464
|
}
|
|
362
|
-
return { name: candidate.name, version: candidate.version };
|
|
363
465
|
}
|
|
364
466
|
function resolveInside(root, path) {
|
|
365
467
|
if (!isManifestPath(path)) throw new Error(`Runtime manifest contains an unsafe path ${path}`);
|
|
@@ -381,6 +483,9 @@ function isValidSize(value) {
|
|
|
381
483
|
function isSha256(value) {
|
|
382
484
|
return typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
|
|
383
485
|
}
|
|
486
|
+
function isTreeIntegrity(value) {
|
|
487
|
+
return isRecord(value) && isManifestPath(value.path) && isValidSize(value.files) && isValidSize(value.bytes) && isSha256(value.sha256);
|
|
488
|
+
}
|
|
384
489
|
function isDestinationRace(error) {
|
|
385
490
|
const code = error.code;
|
|
386
491
|
return code === "EEXIST" || code === "ENOTEMPTY";
|
package/dist/installer.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/entry/installer.ts", "../src/platform/install/service-installer.ts", "../src/platform/install/service-definition.ts", "../src/platform/install/runtime-release.ts", "../src/platform/install/tree-integrity.ts", "../src/platform/shared/paths.ts"],
|
|
4
|
-
"sourcesContent": ["import { execFile } from \"node:child_process\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { promisify } from \"node:util\";\n\nimport {\n installUserService,\n uninstallUserService,\n type CommandExecutor,\n} from \"../platform/install/service-installer.js\";\nimport { materializeRuntime } from \"../platform/install/runtime-release.js\";\nimport { resolveApplicationRoot, resolveFleetPaths } from \"../platform/shared/paths.js\";\n\nconst executor: CommandExecutor = {\n async run(command, args) {\n await promisify(execFile)(command, [...args]);\n },\n};\n\nexport async function installRuntimeService(): Promise<string> {\n return installMaterializedService(resolveFleetPaths().stateRoot);\n}\n\nexport async function repairRuntimeService(): Promise<string> {\n return installMaterializedService(process.env.PIFLEET_STATE_ROOT);\n}\n\nasync function installMaterializedService(stateRoot: string | undefined): Promise<string> {\n const sourceRoot = dirname(dirname(fileURLToPath(import.meta.url)));\n const release = await materializeRuntime({\n sourceRoot,\n applicationRoot: resolveApplicationRoot(),\n });\n return installUserService({\n platform: process.platform,\n definition: {\n nodePath: process.execPath,\n runtimePath: join(release, \"bin\", \"pifleet-runtime.mjs\"),\n ...(stateRoot === undefined ? {} : { stateRoot }),\n },\n executor,\n });\n}\n\nexport async function uninstallRuntimeService(): Promise<void> {\n await uninstallUserService({ platform: process.platform, executor });\n}\n\nasync function main(): Promise<void> {\n const command = process.argv[2];\n if (command === \"install\") {\n process.stdout.write(`${await installRuntimeService()}\\n`);\n return;\n }\n if (command === \"repair\") {\n process.stdout.write(`${await repairRuntimeService()}\\n`);\n return;\n }\n if (command === \"uninstall\") {\n await uninstallRuntimeService();\n return;\n }\n throw new Error(\"Usage: node dist/installer.mjs <install|repair|uninstall>\");\n}\n\nif (process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href) {\n await main();\n}\n", "import { constants } from \"node:fs\";\nimport { access, chmod, mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n launchdAgentPlist,\n systemdUserUnit,\n type ServiceDefinitionOptions,\n} from \"./service-definition.js\";\n\nexport interface CommandExecutor {\n run(command: string, args: readonly string[]): Promise<void>;\n}\n\nexport async function installUserService(options: {\n readonly platform: NodeJS.Platform;\n readonly definition: ServiceDefinitionOptions;\n readonly executor: CommandExecutor;\n readonly home?: string;\n readonly uid?: number;\n}): Promise<string> {\n const home = options.home ?? homedir();\n if (options.platform === \"linux\") {\n const path = join(home, \".config\", \"systemd\", \"user\", \"pi-fleet.service\");\n const effectiveDefinition = await preserveInstalledStateRoot(path, options.definition, \"linux\");\n const definition = systemdUserUnit(effectiveDefinition);\n const needsRepair = await serviceDefinitionNeedsRepair(path, definition, effectiveDefinition);\n if (needsRepair) {\n await atomicWrite(path, definition);\n await options.executor.run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n }\n await options.executor.run(\"systemctl\", [\"--user\", \"enable\", \"--now\", \"pi-fleet.service\"]);\n if (needsRepair) {\n await options.executor.run(\"systemctl\", [\"--user\", \"restart\", \"pi-fleet.service\"]);\n }\n return path;\n }\n if (options.platform === \"darwin\") {\n const path = join(home, \"Library\", \"LaunchAgents\", \"works.elpapi.pifleet.plist\");\n const effectiveDefinition = await preserveInstalledStateRoot(\n path,\n options.definition,\n \"darwin\",\n );\n await atomicWrite(path, launchdAgentPlist(effectiveDefinition));\n const domain = `gui/${options.uid ?? process.getuid?.() ?? 0}`;\n await options.executor.run(\"launchctl\", [\"bootout\", domain, path]).catch(() => undefined);\n await options.executor.run(\"launchctl\", [\"bootstrap\", domain, path]);\n await options.executor.run(\"launchctl\", [\"kickstart\", `${domain}/works.elpapi.pifleet`]);\n return path;\n }\n throw new Error(`Native Pi Fleet supervision is unsupported on ${options.platform}`);\n}\n\nexport async function uninstallUserService(options: {\n readonly platform: NodeJS.Platform;\n readonly executor: CommandExecutor;\n readonly home?: string;\n readonly uid?: number;\n}): Promise<void> {\n const home = options.home ?? homedir();\n if (options.platform === \"linux\") {\n const path = join(home, \".config\", \"systemd\", \"user\", \"pi-fleet.service\");\n await options.executor.run(\"systemctl\", [\"--user\", \"disable\", \"--now\", \"pi-fleet.service\"]);\n await rm(path, { force: true });\n await options.executor.run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n return;\n }\n if (options.platform === \"darwin\") {\n const path = join(home, \"Library\", \"LaunchAgents\", \"works.elpapi.pifleet.plist\");\n const domain = `gui/${options.uid ?? process.getuid?.() ?? 0}`;\n await options.executor.run(\"launchctl\", [\"bootout\", domain, path]).catch(() => undefined);\n await rm(path, { force: true });\n return;\n }\n throw new Error(`Native Pi Fleet supervision is unsupported on ${options.platform}`);\n}\n\nexport async function serviceDefinitionNeedsRepair(\n path: string,\n expectedContents: string,\n definition: ServiceDefinitionOptions,\n): Promise<boolean> {\n const current = await readFile(path, \"utf8\").catch((error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return null;\n throw error;\n });\n if (current !== expectedContents) return true;\n try {\n await access(definition.nodePath, constants.X_OK);\n await access(definition.runtimePath, constants.R_OK);\n return false;\n } catch {\n return true;\n }\n}\n\nasync function preserveInstalledStateRoot(\n path: string,\n definition: ServiceDefinitionOptions,\n platform: \"linux\" | \"darwin\",\n): Promise<ServiceDefinitionOptions> {\n if (definition.stateRoot !== undefined) return definition;\n const current = await readFile(path, \"utf8\").catch((error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return null;\n throw error;\n });\n if (current === null) return definition;\n const encoded =\n platform === \"linux\"\n ? /^Environment=PIFLEET_STATE_ROOT=(.+)$/m.exec(current)?.[1]\n : /<key>PIFLEET_STATE_ROOT<\\/key><string>([^<]+)<\\/string>/.exec(current)?.[1];\n if (encoded === undefined) return definition;\n const stateRoot =\n platform === \"linux\"\n ? encoded\n : encoded\n .replaceAll(\"'\", \"'\")\n .replaceAll(\""\", '\"')\n .replaceAll(\">\", \">\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\"&\", \"&\");\n return { ...definition, stateRoot };\n}\n\nasync function atomicWrite(path: string, contents: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true, mode: 0o700 });\n const temporary = `${path}.tmp-${process.pid}`;\n await writeFile(temporary, contents, { mode: 0o600 });\n await chmod(temporary, 0o600);\n await rename(temporary, path);\n}\n", "import { isAbsolute } from \"node:path\";\n\nexport interface ServiceDefinitionOptions {\n readonly nodePath: string;\n readonly runtimePath: string;\n readonly stateRoot?: string;\n}\n\nexport function systemdUserUnit(options: ServiceDefinitionOptions): string {\n validate(options);\n const environment =\n options.stateRoot === undefined\n ? \"\"\n : `Environment=PIFLEET_STATE_ROOT=${systemdEscape(options.stateRoot)}\\n`;\n return `[Unit]\nDescription=Pi Fleet user runtime\nAfter=default.target\n\n[Service]\nType=simple\nExecStart=${systemdEscape(options.nodePath)} ${systemdEscape(options.runtimePath)}\n${environment}Restart=on-failure\nRestartSec=1\nTimeoutStopSec=10\nUMask=0077\nKillMode=control-group\n\n[Install]\nWantedBy=default.target\n`;\n}\n\nexport function launchdAgentPlist(options: ServiceDefinitionOptions): string {\n validate(options);\n const environment =\n options.stateRoot === undefined\n ? \"\"\n : ` <key>EnvironmentVariables</key>\n <dict><key>PIFLEET_STATE_ROOT</key><string>${xmlEscape(options.stateRoot)}</string></dict>\n`;\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key><string>works.elpapi.pifleet</string>\n <key>ProgramArguments</key>\n <array>\n <string>${xmlEscape(options.nodePath)}</string>\n <string>${xmlEscape(options.runtimePath)}</string>\n </array>\n${environment} <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>\n <key>ProcessType</key><string>Background</string>\n</dict>\n</plist>\n`;\n}\n\nfunction validate(options: ServiceDefinitionOptions): void {\n if (!isAbsolute(options.nodePath) || !isAbsolute(options.runtimePath)) {\n throw new Error(\"Service executables must use absolute paths\");\n }\n}\n\nfunction systemdEscape(value: string): string {\n if (!/^[A-Za-z0-9_./:@-]+$/.test(value)) throw new Error(`Unsafe systemd path ${value}`);\n return value;\n}\n\nfunction xmlEscape(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n}\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport { chmod, cp, lstat, mkdir, readFile, rename, rm } from \"node:fs/promises\";\nimport { join, posix, resolve, sep } from \"node:path\";\n\nimport { hashDirectoryTree, type TreeIntegrity } from \"./tree-integrity.js\";\n\ninterface RuntimeManifestFile {\n readonly path: string;\n readonly bytes: number;\n readonly sha256: string;\n}\n\ninterface RuntimeManifest {\n readonly schemaVersion: 2;\n readonly package: { readonly name: string; readonly version: string };\n readonly files: readonly RuntimeManifestFile[];\n readonly trees: readonly TreeIntegrity[];\n}\n\nconst requiredRuntimeArtifacts = new Set([\n \"package.json\",\n \"bin/pifleet.mjs\",\n \"bin/pifleet-runtime.mjs\",\n \"dist/cli.mjs\",\n \"dist/runtime.mjs\",\n \"dist/sqlite-worker.mjs\",\n]);\n\nexport async function materializeRuntime(options: {\n readonly sourceRoot: string;\n readonly applicationRoot: string;\n}): Promise<string> {\n const sourceRoot = resolve(options.sourceRoot);\n const manifestBytes = await readFile(join(sourceRoot, \"dist\", \"runtime-manifest.json\"));\n const manifest = await parseRuntimeManifest(manifestBytes, sourceRoot);\n await verifyRuntime(sourceRoot, manifest);\n\n const applicationRoot = resolve(options.applicationRoot);\n await ensurePrivateDirectory(applicationRoot);\n const manifestHash = createHash(\"sha256\").update(manifestBytes).digest(\"hex\").slice(0, 16);\n const releasesRoot = join(applicationRoot, \"releases\");\n await ensurePrivateDirectory(releasesRoot);\n const destination = join(releasesRoot, `${manifest.package.version}-${manifestHash}`);\n\n if (await pathExists(destination)) {\n await verifyRuntime(destination, manifest);\n return destination;\n }\n\n const staging = join(releasesRoot, `.staging-${randomUUID()}`);\n await mkdir(staging, { mode: 0o700 });\n try {\n await cp(join(sourceRoot, \"dist\"), join(staging, \"dist\"), {\n recursive: true,\n dereference: true,\n });\n await cp(join(sourceRoot, \"bin\"), join(staging, \"bin\"), { recursive: true, dereference: true });\n await cp(join(sourceRoot, \"package.json\"), join(staging, \"package.json\"));\n for (const tree of manifest.trees) {\n const source = resolveInside(sourceRoot, tree.path);\n const destination = resolveInside(staging, tree.path);\n await mkdir(resolve(destination, \"..\"), { recursive: true, mode: 0o700 });\n await cp(source, destination, { recursive: true, dereference: true });\n }\n await verifyRuntime(staging, manifest);\n await chmod(staging, 0o700);\n try {\n await rename(staging, destination);\n } catch (error: unknown) {\n if (!isDestinationRace(error) || !(await pathExists(destination))) throw error;\n await verifyRuntime(destination, manifest);\n }\n return destination;\n } finally {\n await rm(staging, { recursive: true, force: true });\n }\n}\n\nexport async function verifyRuntime(root: string, manifest?: RuntimeManifest): Promise<void> {\n const resolvedRoot = resolve(root);\n const expected =\n manifest ??\n (await parseRuntimeManifest(\n await readFile(join(resolvedRoot, \"dist\", \"runtime-manifest.json\")),\n resolvedRoot,\n ));\n if (manifest !== undefined) await validateRuntimeManifest(manifest, resolvedRoot);\n\n for (const file of expected.files) {\n const path = resolveInside(resolvedRoot, file.path);\n const info = await lstat(path);\n if (info.isSymbolicLink()) {\n throw new Error(`Runtime artifact ${file.path} must not be a symbolic link`);\n }\n if (!info.isFile() || info.size !== file.bytes) {\n throw new Error(`Runtime artifact ${file.path} has changed`);\n }\n const hash = createHash(\"sha256\")\n .update(await readFile(path))\n .digest(\"hex\");\n if (hash !== file.sha256) {\n throw new Error(`Runtime artifact ${file.path} failed verification`);\n }\n }\n for (const expectedTree of expected.trees) {\n const treeRoot = resolveInside(resolvedRoot, expectedTree.path);\n const actualTree = await hashDirectoryTree(treeRoot, expectedTree.path);\n if (\n actualTree.files !== expectedTree.files ||\n actualTree.bytes !== expectedTree.bytes ||\n actualTree.sha256 !== expectedTree.sha256\n ) {\n throw new Error(`Runtime dependency tree ${expectedTree.path} failed verification`);\n }\n }\n}\n\nasync function parseRuntimeManifest(bytes: Buffer, root: string): Promise<RuntimeManifest> {\n let candidate: unknown;\n try {\n candidate = JSON.parse(bytes.toString(\"utf8\"));\n } catch {\n throw new Error(\"Runtime manifest is not valid JSON\");\n }\n await validateRuntimeManifest(candidate, root);\n return candidate as RuntimeManifest;\n}\n\nasync function validateRuntimeManifest(candidate: unknown, root: string): Promise<void> {\n if (!isRecord(candidate) || candidate.schemaVersion !== 2) {\n throw new Error(\"Runtime manifest has an unsupported schema version\");\n }\n if (\n !isRecord(candidate.package) ||\n typeof candidate.package.name !== \"string\" ||\n typeof candidate.package.version !== \"string\"\n ) {\n throw new Error(\"Runtime manifest has an invalid package identity\");\n }\n const packageIdentity = await readPackageIdentity(root);\n if (\n candidate.package.name !== packageIdentity.name ||\n candidate.package.version !== packageIdentity.version\n ) {\n throw new Error(\"Runtime manifest package identity does not match package.json\");\n }\n if (!Array.isArray(candidate.files) || !Array.isArray(candidate.trees)) {\n throw new Error(\"Runtime manifest has invalid artifact lists\");\n }\n\n const filePaths = new Set<string>();\n for (const file of candidate.files) {\n if (\n !isRecord(file) ||\n !isManifestPath(file.path) ||\n !isValidSize(file.bytes) ||\n !isSha256(file.sha256)\n ) {\n throw new Error(\"Runtime manifest contains an invalid artifact\");\n }\n if (filePaths.has(file.path))\n throw new Error(`Runtime manifest has duplicate path ${file.path}`);\n filePaths.add(file.path);\n }\n for (const required of requiredRuntimeArtifacts) {\n if (!filePaths.has(required)) {\n throw new Error(`Runtime manifest is missing required artifact ${required}`);\n }\n }\n\n const treePaths = new Set<string>();\n for (const tree of candidate.trees) {\n if (\n !isRecord(tree) ||\n !isManifestPath(tree.path) ||\n !isValidSize(tree.files) ||\n !isValidSize(tree.bytes) ||\n !isSha256(tree.sha256)\n ) {\n throw new Error(\"Runtime manifest contains an invalid dependency tree\");\n }\n if (treePaths.has(tree.path))\n throw new Error(`Runtime manifest has duplicate path ${tree.path}`);\n treePaths.add(tree.path);\n }\n const allPaths = [...filePaths, ...treePaths];\n for (let index = 0; index < allPaths.length; index += 1) {\n for (let other = index + 1; other < allPaths.length; other += 1) {\n const left = allPaths[index]!;\n const right = allPaths[other]!;\n if (left === right || left.startsWith(`${right}/`) || right.startsWith(`${left}/`)) {\n throw new Error(`Runtime manifest has overlapping paths ${left} and ${right}`);\n }\n }\n }\n}\n\nasync function readPackageIdentity(root: string): Promise<{ name: string; version: string }> {\n let candidate: unknown;\n try {\n candidate = JSON.parse(await readFile(join(root, \"package.json\"), \"utf8\"));\n } catch {\n throw new Error(\"Runtime package.json is not valid JSON\");\n }\n if (\n !isRecord(candidate) ||\n typeof candidate.name !== \"string\" ||\n typeof candidate.version !== \"string\"\n ) {\n throw new Error(\"Runtime package.json has an invalid identity\");\n }\n return { name: candidate.name, version: candidate.version };\n}\n\nfunction resolveInside(root: string, path: string): string {\n if (!isManifestPath(path)) throw new Error(`Runtime manifest contains an unsafe path ${path}`);\n const resolved = resolve(root, path);\n if (!resolved.startsWith(`${root}${sep}`)) {\n throw new Error(`Runtime manifest contains an unsafe path ${path}`);\n }\n return resolved;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isManifestPath(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n value.length > 0 &&\n !value.includes(\"\\\\\") &&\n !value.startsWith(\"/\") &&\n posix.normalize(value) === value &&\n value.split(\"/\").every((part) => part.length > 0 && part !== \".\" && part !== \"..\")\n );\n}\n\nfunction isValidSize(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction isSha256(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-f0-9]{64}$/.test(value);\n}\n\nfunction isDestinationRace(error: unknown): boolean {\n const code = (error as NodeJS.ErrnoException).code;\n return code === \"EEXIST\" || code === \"ENOTEMPTY\";\n}\n\nasync function ensurePrivateDirectory(path: string): Promise<void> {\n await mkdir(path, { recursive: true, mode: 0o700 });\n const info = await lstat(path);\n if (!info.isDirectory() || info.isSymbolicLink()) {\n throw new Error(`Refusing unsafe runtime release path ${path}`);\n }\n if (typeof process.getuid === \"function\" && info.uid !== process.getuid()) {\n throw new Error(`Runtime release path ${path} is not owned by the current user`);\n }\n await chmod(path, 0o700);\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await lstat(path);\n return true;\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw error;\n }\n}\n", "import { createHash } from \"node:crypto\";\nimport { lstat, readFile, readdir, stat } from \"node:fs/promises\";\nimport { join, relative, resolve, sep } from \"node:path\";\n\nexport interface TreeIntegrity {\n readonly path: string;\n readonly files: number;\n readonly bytes: number;\n readonly sha256: string;\n}\n\nexport async function hashDirectoryTree(\n root: string,\n manifestPath: string,\n): Promise<TreeIntegrity> {\n const resolvedRoot = resolve(root);\n const entries = await collectFiles(resolvedRoot, resolvedRoot);\n const hash = createHash(\"sha256\");\n let bytes = 0;\n for (const entry of entries) {\n const contents = await readFile(entry.absolutePath);\n bytes += contents.length;\n hash.update(entry.relativePath);\n hash.update(\"\\0\");\n hash.update(String(contents.length));\n hash.update(\"\\0\");\n hash.update(contents);\n hash.update(\"\\0\");\n }\n return {\n path: manifestPath,\n files: entries.length,\n bytes,\n sha256: hash.digest(\"hex\"),\n };\n}\n\nasync function collectFiles(\n root: string,\n directory: string,\n): Promise<Array<{ readonly absolutePath: string; readonly relativePath: string }>> {\n const output: Array<{ absolutePath: string; relativePath: string }> = [];\n for (const name of (await readdir(directory)).sort()) {\n const absolutePath = join(directory, name);\n const linkInfo = await lstat(absolutePath);\n const info = linkInfo.isSymbolicLink() ? await stat(absolutePath) : linkInfo;\n if (info.isDirectory()) {\n if (linkInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency tree contains a directory symlink: ${absolutePath}`);\n }\n output.push(...(await collectFiles(root, absolutePath)));\n continue;\n }\n if (!info.isFile()) {\n throw new Error(`Runtime dependency tree contains an unsupported entry: ${absolutePath}`);\n }\n const relativePath = relative(root, absolutePath).split(sep).join(\"/\");\n if (relativePath.length === 0 || relativePath.startsWith(\"../\")) {\n throw new Error(`Runtime dependency path escapes its root: ${absolutePath}`);\n }\n output.push({ absolutePath, relativePath });\n }\n return output.sort((left, right) => left.relativePath.localeCompare(right.relativePath));\n}\n", "import { homedir, tmpdir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nexport interface FleetPaths {\n readonly runtimeRoot: string;\n readonly stateRoot: string;\n readonly socketPath: string;\n readonly databasePath: string;\n}\n\nexport function resolveApplicationRoot(env: NodeJS.ProcessEnv = process.env): string {\n return (\n env.PIFLEET_APPLICATION_ROOT ??\n (process.platform === \"darwin\"\n ? join(homedir(), \"Library\", \"Application Support\", \"Pi Fleet\", \"runtime\")\n : join(env.XDG_DATA_HOME ?? join(homedir(), \".local\", \"share\"), \"pi-fleet\"))\n );\n}\n\nexport function resolveFleetPaths(env: NodeJS.ProcessEnv = process.env): FleetPaths {\n const explicitRoot = env.PIFLEET_STATE_ROOT;\n if (explicitRoot !== undefined) {\n const root = resolve(explicitRoot);\n return {\n runtimeRoot: root,\n stateRoot: root,\n socketPath: join(root, \"control.sock\"),\n databasePath: join(root, \"fleet.sqlite\"),\n };\n }\n\n const runtimeRoot = join(\n env.XDG_RUNTIME_DIR ?? tmpdir(),\n `pifleet-${process.getuid?.() ?? \"user\"}`,\n );\n const stateRoot =\n process.platform === \"darwin\"\n ? join(homedir(), \"Library\", \"Application Support\", \"Pi Fleet\")\n : join(env.XDG_STATE_HOME ?? join(homedir(), \".local\", \"state\"), \"pi-fleet\");\n return {\n runtimeRoot,\n stateRoot,\n socketPath: join(runtimeRoot, \"control.sock\"),\n databasePath: join(stateRoot, \"fleet.sqlite\"),\n };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["dirname", "join", "createHash", "chmod", "lstat", "mkdir", "readFile", "rename", "rm", "join", "resolve", "sep", "readFile", "join", "resolve", "readFile", "join", "createHash", "mkdir", "
|
|
4
|
+
"sourcesContent": ["import { execFile } from \"node:child_process\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { promisify } from \"node:util\";\n\nimport {\n installUserService,\n uninstallUserService,\n type CommandExecutor,\n} from \"../platform/install/service-installer.js\";\nimport { materializeRuntime } from \"../platform/install/runtime-release.js\";\nimport { resolveApplicationRoot, resolveFleetPaths } from \"../platform/shared/paths.js\";\n\nconst executor: CommandExecutor = {\n async run(command, args) {\n await promisify(execFile)(command, [...args]);\n },\n};\n\nexport async function installRuntimeService(): Promise<string> {\n return installMaterializedService(resolveFleetPaths().stateRoot);\n}\n\nexport async function repairRuntimeService(): Promise<string> {\n return installMaterializedService(process.env.PIFLEET_STATE_ROOT);\n}\n\nasync function installMaterializedService(stateRoot: string | undefined): Promise<string> {\n const sourceRoot = dirname(dirname(fileURLToPath(import.meta.url)));\n const release = await materializeRuntime({\n sourceRoot,\n applicationRoot: resolveApplicationRoot(),\n });\n return installUserService({\n platform: process.platform,\n definition: {\n nodePath: process.execPath,\n runtimePath: join(release, \"bin\", \"pifleet-runtime.mjs\"),\n ...(stateRoot === undefined ? {} : { stateRoot }),\n },\n executor,\n });\n}\n\nexport async function uninstallRuntimeService(): Promise<void> {\n await uninstallUserService({ platform: process.platform, executor });\n}\n\nasync function main(): Promise<void> {\n const command = process.argv[2];\n if (command === \"install\") {\n process.stdout.write(`${await installRuntimeService()}\\n`);\n return;\n }\n if (command === \"repair\") {\n process.stdout.write(`${await repairRuntimeService()}\\n`);\n return;\n }\n if (command === \"uninstall\") {\n await uninstallRuntimeService();\n return;\n }\n throw new Error(\"Usage: node dist/installer.mjs <install|repair|uninstall>\");\n}\n\nif (process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href) {\n await main();\n}\n", "import { constants } from \"node:fs\";\nimport { access, chmod, mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n launchdAgentPlist,\n systemdUserUnit,\n type ServiceDefinitionOptions,\n} from \"./service-definition.js\";\n\nexport interface CommandExecutor {\n run(command: string, args: readonly string[]): Promise<void>;\n}\n\nexport async function installUserService(options: {\n readonly platform: NodeJS.Platform;\n readonly definition: ServiceDefinitionOptions;\n readonly executor: CommandExecutor;\n readonly home?: string;\n readonly uid?: number;\n}): Promise<string> {\n const home = options.home ?? homedir();\n if (options.platform === \"linux\") {\n const path = join(home, \".config\", \"systemd\", \"user\", \"pi-fleet.service\");\n const effectiveDefinition = await preserveInstalledStateRoot(path, options.definition, \"linux\");\n const definition = systemdUserUnit(effectiveDefinition);\n const needsRepair = await serviceDefinitionNeedsRepair(path, definition, effectiveDefinition);\n if (needsRepair) {\n await atomicWrite(path, definition);\n await options.executor.run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n }\n await options.executor.run(\"systemctl\", [\"--user\", \"enable\", \"--now\", \"pi-fleet.service\"]);\n if (needsRepair) {\n await options.executor.run(\"systemctl\", [\"--user\", \"restart\", \"pi-fleet.service\"]);\n }\n return path;\n }\n if (options.platform === \"darwin\") {\n const path = join(home, \"Library\", \"LaunchAgents\", \"works.elpapi.pifleet.plist\");\n const effectiveDefinition = await preserveInstalledStateRoot(\n path,\n options.definition,\n \"darwin\",\n );\n await atomicWrite(path, launchdAgentPlist(effectiveDefinition));\n const domain = `gui/${options.uid ?? process.getuid?.() ?? 0}`;\n await options.executor.run(\"launchctl\", [\"bootout\", domain, path]).catch(() => undefined);\n await options.executor.run(\"launchctl\", [\"bootstrap\", domain, path]);\n await options.executor.run(\"launchctl\", [\"kickstart\", `${domain}/works.elpapi.pifleet`]);\n return path;\n }\n throw new Error(`Native Pi Fleet supervision is unsupported on ${options.platform}`);\n}\n\nexport async function uninstallUserService(options: {\n readonly platform: NodeJS.Platform;\n readonly executor: CommandExecutor;\n readonly home?: string;\n readonly uid?: number;\n}): Promise<void> {\n const home = options.home ?? homedir();\n if (options.platform === \"linux\") {\n const path = join(home, \".config\", \"systemd\", \"user\", \"pi-fleet.service\");\n await options.executor.run(\"systemctl\", [\"--user\", \"disable\", \"--now\", \"pi-fleet.service\"]);\n await rm(path, { force: true });\n await options.executor.run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n return;\n }\n if (options.platform === \"darwin\") {\n const path = join(home, \"Library\", \"LaunchAgents\", \"works.elpapi.pifleet.plist\");\n const domain = `gui/${options.uid ?? process.getuid?.() ?? 0}`;\n await options.executor.run(\"launchctl\", [\"bootout\", domain, path]).catch(() => undefined);\n await rm(path, { force: true });\n return;\n }\n throw new Error(`Native Pi Fleet supervision is unsupported on ${options.platform}`);\n}\n\nexport async function serviceDefinitionNeedsRepair(\n path: string,\n expectedContents: string,\n definition: ServiceDefinitionOptions,\n): Promise<boolean> {\n const current = await readFile(path, \"utf8\").catch((error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return null;\n throw error;\n });\n if (current !== expectedContents) return true;\n try {\n await access(definition.nodePath, constants.X_OK);\n await access(definition.runtimePath, constants.R_OK);\n return false;\n } catch {\n return true;\n }\n}\n\nasync function preserveInstalledStateRoot(\n path: string,\n definition: ServiceDefinitionOptions,\n platform: \"linux\" | \"darwin\",\n): Promise<ServiceDefinitionOptions> {\n if (definition.stateRoot !== undefined) return definition;\n const current = await readFile(path, \"utf8\").catch((error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return null;\n throw error;\n });\n if (current === null) return definition;\n const encoded =\n platform === \"linux\"\n ? /^Environment=PIFLEET_STATE_ROOT=(.+)$/m.exec(current)?.[1]\n : /<key>PIFLEET_STATE_ROOT<\\/key><string>([^<]+)<\\/string>/.exec(current)?.[1];\n if (encoded === undefined) return definition;\n const stateRoot =\n platform === \"linux\"\n ? encoded\n : encoded\n .replaceAll(\"'\", \"'\")\n .replaceAll(\""\", '\"')\n .replaceAll(\">\", \">\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\"&\", \"&\");\n return { ...definition, stateRoot };\n}\n\nasync function atomicWrite(path: string, contents: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true, mode: 0o700 });\n const temporary = `${path}.tmp-${process.pid}`;\n await writeFile(temporary, contents, { mode: 0o600 });\n await chmod(temporary, 0o600);\n await rename(temporary, path);\n}\n", "import { isAbsolute } from \"node:path\";\n\nexport interface ServiceDefinitionOptions {\n readonly nodePath: string;\n readonly runtimePath: string;\n readonly stateRoot?: string;\n}\n\nexport function systemdUserUnit(options: ServiceDefinitionOptions): string {\n validate(options);\n const environment =\n options.stateRoot === undefined\n ? \"\"\n : `Environment=PIFLEET_STATE_ROOT=${systemdEscape(options.stateRoot)}\\n`;\n return `[Unit]\nDescription=Pi Fleet user runtime\nAfter=default.target\n\n[Service]\nType=simple\nExecStart=${systemdEscape(options.nodePath)} ${systemdEscape(options.runtimePath)}\n${environment}Restart=on-failure\nRestartSec=1\nTimeoutStopSec=10\nUMask=0077\nKillMode=control-group\n\n[Install]\nWantedBy=default.target\n`;\n}\n\nexport function launchdAgentPlist(options: ServiceDefinitionOptions): string {\n validate(options);\n const environment =\n options.stateRoot === undefined\n ? \"\"\n : ` <key>EnvironmentVariables</key>\n <dict><key>PIFLEET_STATE_ROOT</key><string>${xmlEscape(options.stateRoot)}</string></dict>\n`;\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key><string>works.elpapi.pifleet</string>\n <key>ProgramArguments</key>\n <array>\n <string>${xmlEscape(options.nodePath)}</string>\n <string>${xmlEscape(options.runtimePath)}</string>\n </array>\n${environment} <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>\n <key>ProcessType</key><string>Background</string>\n</dict>\n</plist>\n`;\n}\n\nfunction validate(options: ServiceDefinitionOptions): void {\n if (!isAbsolute(options.nodePath) || !isAbsolute(options.runtimePath)) {\n throw new Error(\"Service executables must use absolute paths\");\n }\n}\n\nfunction systemdEscape(value: string): string {\n if (!/^[A-Za-z0-9_./:@-]+$/.test(value)) throw new Error(`Unsafe systemd path ${value}`);\n return value;\n}\n\nfunction xmlEscape(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n}\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport { chmod, cp, lstat, mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { join, posix, resolve, sep } from \"node:path\";\n\nimport { hashDirectoryTree, type TreeIntegrity } from \"./tree-integrity.js\";\n\ninterface RuntimeManifestFile {\n readonly path: string;\n readonly bytes: number;\n readonly sha256: string;\n}\n\ninterface RuntimeDependency {\n readonly path: string;\n readonly name: string;\n readonly version: string;\n}\n\ninterface RuntimeClosure {\n readonly sourceManifestSha256: string;\n readonly tree: TreeIntegrity;\n}\n\ninterface RuntimeManifest {\n readonly schemaVersion: 3;\n readonly package: { readonly name: string; readonly version: string };\n readonly managedPi: string;\n readonly files: readonly RuntimeManifestFile[];\n readonly dependencies: readonly RuntimeDependency[];\n readonly closure?: RuntimeClosure;\n}\n\ninterface PackageMetadata {\n readonly name: string;\n readonly version: string;\n readonly dependencies: Readonly<Record<string, string>>;\n}\n\nconst requiredRuntimeArtifacts = new Set([\n \"package.json\",\n \"bin/pifleet.mjs\",\n \"bin/pifleet-runtime.mjs\",\n \"dist/cli.mjs\",\n \"dist/runtime.mjs\",\n \"dist/sqlite-worker.mjs\",\n]);\nconst dependencyTreePath = \"node_modules\";\n\nexport async function materializeRuntime(options: {\n readonly sourceRoot: string;\n readonly applicationRoot: string;\n readonly hooks?: {\n readonly afterDependencyCopy?: () => Promise<void>;\n };\n}): Promise<string> {\n const sourceRoot = resolve(options.sourceRoot);\n const manifestBytes = await readFile(join(sourceRoot, \"dist\", \"runtime-manifest.json\"));\n const sourceManifest = await parseRuntimeManifest(manifestBytes, sourceRoot);\n if (sourceManifest.closure !== undefined) {\n await verifyRuntime(sourceRoot);\n return sourceRoot;\n }\n await verifyRuntimeFiles(sourceRoot, sourceManifest);\n await verifyDependencyIdentities(sourceRoot, sourceManifest.dependencies);\n\n const sourceTreeRoot = resolveInside(sourceRoot, dependencyTreePath);\n const sourceTreeBefore = await hashDirectoryTree(sourceTreeRoot, dependencyTreePath);\n const sourceManifestSha256 = createHash(\"sha256\").update(manifestBytes).digest(\"hex\");\n const materializedManifest: RuntimeManifest = {\n ...sourceManifest,\n closure: { sourceManifestSha256, tree: sourceTreeBefore },\n };\n const materializedManifestBytes = serializeManifest(materializedManifest);\n const closureHash = createHash(\"sha256\")\n .update(sourceManifestSha256)\n .update(\"\\0\")\n .update(JSON.stringify(sourceTreeBefore))\n .digest(\"hex\")\n .slice(0, 16);\n\n const applicationRoot = resolve(options.applicationRoot);\n await ensurePrivateDirectory(applicationRoot);\n const releasesRoot = join(applicationRoot, \"releases\");\n await ensurePrivateDirectory(releasesRoot);\n const destination = join(releasesRoot, `${sourceManifest.package.version}-${closureHash}`);\n\n if (await pathExists(destination)) {\n await verifyExpectedRuntime(destination, materializedManifest, materializedManifestBytes);\n return destination;\n }\n\n const staging = join(releasesRoot, `.staging-${randomUUID()}`);\n await mkdir(staging, { mode: 0o700 });\n try {\n await cp(join(sourceRoot, \"dist\"), join(staging, \"dist\"), {\n recursive: true,\n dereference: true,\n });\n await cp(join(sourceRoot, \"bin\"), join(staging, \"bin\"), {\n recursive: true,\n dereference: true,\n });\n await cp(join(sourceRoot, \"package.json\"), join(staging, \"package.json\"));\n await cp(sourceTreeRoot, join(staging, dependencyTreePath), {\n recursive: true,\n dereference: true,\n });\n await options.hooks?.afterDependencyCopy?.();\n\n const stagedTree = await hashDirectoryTree(\n join(staging, dependencyTreePath),\n dependencyTreePath,\n );\n assertSameTree(sourceTreeBefore, stagedTree, \"copied dependency closure\");\n const sourceTreeAfter = await hashDirectoryTree(sourceTreeRoot, dependencyTreePath);\n assertSameTree(sourceTreeBefore, sourceTreeAfter, \"source dependency closure\");\n\n await writeFile(join(staging, \"dist\", \"runtime-manifest.json\"), materializedManifestBytes);\n await verifyExpectedRuntime(staging, materializedManifest, materializedManifestBytes);\n await chmod(staging, 0o700);\n try {\n await rename(staging, destination);\n } catch (error: unknown) {\n if (!isDestinationRace(error) || !(await pathExists(destination))) throw error;\n await verifyExpectedRuntime(destination, materializedManifest, materializedManifestBytes);\n }\n return destination;\n } finally {\n await rm(staging, { recursive: true, force: true });\n }\n}\n\nexport async function verifyRuntime(root: string): Promise<void> {\n const resolvedRoot = resolve(root);\n const manifestBytes = await readFile(join(resolvedRoot, \"dist\", \"runtime-manifest.json\"));\n const manifest = await parseRuntimeManifest(manifestBytes, resolvedRoot);\n if (manifest.closure === undefined) {\n throw new Error(\"Runtime release manifest is missing its materialized closure\");\n }\n await verifyRuntimeFiles(resolvedRoot, manifest);\n await verifyDependencyIdentities(resolvedRoot, manifest.dependencies);\n const actualTree = await hashDirectoryTree(\n resolveInside(resolvedRoot, dependencyTreePath),\n dependencyTreePath,\n );\n assertSameTree(manifest.closure.tree, actualTree, \"materialized dependency closure\");\n}\n\nasync function verifyExpectedRuntime(\n root: string,\n expected: RuntimeManifest,\n expectedBytes: Buffer,\n): Promise<void> {\n const manifestPath = join(root, \"dist\", \"runtime-manifest.json\");\n const actualBytes = await readFile(manifestPath);\n if (!actualBytes.equals(expectedBytes)) {\n throw new Error(\"Materialized runtime manifest does not match the expected closure\");\n }\n const actual = await parseRuntimeManifest(actualBytes, root);\n if (actual.closure === undefined || expected.closure === undefined) {\n throw new Error(\"Materialized runtime manifest is missing its closure\");\n }\n await verifyRuntimeFiles(root, actual);\n await verifyDependencyIdentities(root, actual.dependencies);\n const actualTree = await hashDirectoryTree(\n resolveInside(root, dependencyTreePath),\n dependencyTreePath,\n );\n assertSameTree(expected.closure.tree, actualTree, \"materialized dependency closure\");\n}\n\nasync function verifyRuntimeFiles(root: string, manifest: RuntimeManifest): Promise<void> {\n for (const file of manifest.files) {\n const path = resolveInside(root, file.path);\n const info = await lstat(path);\n if (info.isSymbolicLink()) {\n throw new Error(`Runtime artifact ${file.path} must not be a symbolic link`);\n }\n if (!info.isFile() || info.size !== file.bytes) {\n throw new Error(`Runtime artifact ${file.path} has changed`);\n }\n const hash = createHash(\"sha256\")\n .update(await readFile(path))\n .digest(\"hex\");\n if (hash !== file.sha256) {\n throw new Error(`Runtime artifact ${file.path} failed verification`);\n }\n }\n}\n\nasync function verifyDependencyIdentities(\n root: string,\n dependencies: readonly RuntimeDependency[],\n): Promise<void> {\n const nodeModules = resolveInside(root, dependencyTreePath);\n const modulesInfo = await lstat(nodeModules);\n if (!modulesInfo.isDirectory() || modulesInfo.isSymbolicLink()) {\n throw new Error(\"Runtime dependency closure must be a regular directory\");\n }\n for (const dependency of dependencies) {\n const packageRoot = resolveInside(root, dependency.path);\n const packageInfo = await lstat(packageRoot);\n if (!packageInfo.isDirectory() || packageInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency ${dependency.name} must be a regular directory`);\n }\n const packageJsonPath = join(packageRoot, \"package.json\");\n const packageJsonInfo = await lstat(packageJsonPath);\n if (!packageJsonInfo.isFile() || packageJsonInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency ${dependency.name} has an unsafe package.json`);\n }\n const identity = await readPackageMetadata(packageRoot);\n if (identity.name !== dependency.name || identity.version !== dependency.version) {\n throw new Error(`Runtime dependency ${dependency.name} has an unexpected identity`);\n }\n }\n}\n\nasync function parseRuntimeManifest(bytes: Buffer, root: string): Promise<RuntimeManifest> {\n let candidate: unknown;\n try {\n candidate = JSON.parse(bytes.toString(\"utf8\"));\n } catch {\n throw new Error(\"Runtime manifest is not valid JSON\");\n }\n await validateRuntimeManifest(candidate, root);\n return candidate as RuntimeManifest;\n}\n\nasync function validateRuntimeManifest(candidate: unknown, root: string): Promise<void> {\n if (!isRecord(candidate) || candidate.schemaVersion !== 3) {\n throw new Error(\"Runtime manifest has an unsupported schema version\");\n }\n if (\n !isRecord(candidate.package) ||\n typeof candidate.package.name !== \"string\" ||\n typeof candidate.package.version !== \"string\" ||\n typeof candidate.managedPi !== \"string\"\n ) {\n throw new Error(\"Runtime manifest has an invalid package identity\");\n }\n const packageMetadata = await readPackageMetadata(root);\n if (\n candidate.package.name !== packageMetadata.name ||\n candidate.package.version !== packageMetadata.version\n ) {\n throw new Error(\"Runtime manifest package identity does not match package.json\");\n }\n if (!Array.isArray(candidate.files) || !Array.isArray(candidate.dependencies)) {\n throw new Error(\"Runtime manifest has invalid artifact lists\");\n }\n\n const filePaths = new Set<string>();\n for (const file of candidate.files) {\n if (\n !isRecord(file) ||\n !isManifestPath(file.path) ||\n !isValidSize(file.bytes) ||\n !isSha256(file.sha256)\n ) {\n throw new Error(\"Runtime manifest contains an invalid artifact\");\n }\n if (filePaths.has(file.path)) {\n throw new Error(`Runtime manifest has duplicate path ${file.path}`);\n }\n filePaths.add(file.path);\n }\n for (const required of requiredRuntimeArtifacts) {\n if (!filePaths.has(required)) {\n throw new Error(`Runtime manifest is missing required artifact ${required}`);\n }\n }\n\n const dependencyPaths = new Set<string>();\n const dependencyNames = new Set<string>();\n for (const dependency of candidate.dependencies) {\n if (\n !isRecord(dependency) ||\n !isManifestPath(dependency.path) ||\n typeof dependency.name !== \"string\" ||\n dependency.name.length === 0 ||\n typeof dependency.version !== \"string\" ||\n dependency.version.length === 0 ||\n dependency.path !== `node_modules/${dependency.name}`\n ) {\n throw new Error(\"Runtime manifest contains an invalid dependency declaration\");\n }\n if (dependencyPaths.has(dependency.path) || dependencyNames.has(dependency.name)) {\n throw new Error(`Runtime manifest has duplicate dependency ${dependency.name}`);\n }\n dependencyPaths.add(dependency.path);\n dependencyNames.add(dependency.name);\n }\n const expectedDependencies = packageMetadata.dependencies;\n if (\n dependencyNames.size !== Object.keys(expectedDependencies).length ||\n [...dependencyNames].some(\n (name) =>\n expectedDependencies[name] !==\n (candidate.dependencies as Array<Record<string, unknown>>).find(\n (dependency) => dependency.name === name,\n )?.version,\n )\n ) {\n throw new Error(\"Runtime manifest dependencies do not match package.json\");\n }\n\n for (const filePath of filePaths) {\n for (const dependencyPath of dependencyPaths) {\n if (\n filePath === dependencyPath ||\n filePath.startsWith(`${dependencyPath}/`) ||\n dependencyPath.startsWith(`${filePath}/`)\n ) {\n throw new Error(`Runtime manifest has overlapping paths ${filePath} and ${dependencyPath}`);\n }\n }\n }\n\n if (candidate.closure !== undefined) {\n if (\n !isRecord(candidate.closure) ||\n !isSha256(candidate.closure.sourceManifestSha256) ||\n !isTreeIntegrity(candidate.closure.tree) ||\n candidate.closure.tree.path !== dependencyTreePath\n ) {\n throw new Error(\"Runtime manifest contains an invalid materialized closure\");\n }\n }\n}\n\nasync function readPackageMetadata(root: string): Promise<PackageMetadata> {\n let candidate: unknown;\n try {\n candidate = JSON.parse(await readFile(join(root, \"package.json\"), \"utf8\"));\n } catch {\n throw new Error(\"Runtime package.json is not valid JSON\");\n }\n if (\n !isRecord(candidate) ||\n typeof candidate.name !== \"string\" ||\n typeof candidate.version !== \"string\" ||\n (candidate.dependencies !== undefined && !isRecord(candidate.dependencies)) ||\n (isRecord(candidate.dependencies) &&\n Object.values(candidate.dependencies).some((version) => typeof version !== \"string\"))\n ) {\n throw new Error(\"Runtime package.json has invalid package metadata\");\n }\n return {\n name: candidate.name,\n version: candidate.version,\n dependencies: isRecord(candidate.dependencies)\n ? (candidate.dependencies as Record<string, string>)\n : {},\n };\n}\n\nfunction serializeManifest(manifest: RuntimeManifest): Buffer {\n return Buffer.from(`${JSON.stringify(manifest, null, 2)}\\n`);\n}\n\nfunction assertSameTree(expected: TreeIntegrity, actual: TreeIntegrity, label: string): void {\n if (\n expected.path !== actual.path ||\n expected.files !== actual.files ||\n expected.bytes !== actual.bytes ||\n expected.sha256 !== actual.sha256\n ) {\n throw new Error(`Runtime ${label} changed during materialization`);\n }\n}\n\nfunction resolveInside(root: string, path: string): string {\n if (!isManifestPath(path)) throw new Error(`Runtime manifest contains an unsafe path ${path}`);\n const resolved = resolve(root, path);\n if (!resolved.startsWith(`${root}${sep}`)) {\n throw new Error(`Runtime manifest contains an unsafe path ${path}`);\n }\n return resolved;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isManifestPath(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n value.length > 0 &&\n !value.includes(\"\\\\\") &&\n !value.startsWith(\"/\") &&\n posix.normalize(value) === value &&\n value.split(\"/\").every((part) => part.length > 0 && part !== \".\" && part !== \"..\")\n );\n}\n\nfunction isValidSize(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction isSha256(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-f0-9]{64}$/.test(value);\n}\n\nfunction isTreeIntegrity(value: unknown): value is TreeIntegrity {\n return (\n isRecord(value) &&\n isManifestPath(value.path) &&\n isValidSize(value.files) &&\n isValidSize(value.bytes) &&\n isSha256(value.sha256)\n );\n}\n\nfunction isDestinationRace(error: unknown): boolean {\n const code = (error as NodeJS.ErrnoException).code;\n return code === \"EEXIST\" || code === \"ENOTEMPTY\";\n}\n\nasync function ensurePrivateDirectory(path: string): Promise<void> {\n await mkdir(path, { recursive: true, mode: 0o700 });\n const info = await lstat(path);\n if (!info.isDirectory() || info.isSymbolicLink()) {\n throw new Error(`Refusing unsafe runtime release path ${path}`);\n }\n if (typeof process.getuid === \"function\" && info.uid !== process.getuid()) {\n throw new Error(`Runtime release path ${path} is not owned by the current user`);\n }\n await chmod(path, 0o700);\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await lstat(path);\n return true;\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw error;\n }\n}\n", "import { createHash } from \"node:crypto\";\nimport { lstat, readFile, readdir, realpath, stat } from \"node:fs/promises\";\nimport { join, relative, resolve, sep } from \"node:path\";\n\nexport interface TreeIntegrity {\n readonly path: string;\n readonly files: number;\n readonly bytes: number;\n readonly sha256: string;\n}\n\nexport async function hashDirectoryTree(\n root: string,\n manifestPath: string,\n): Promise<TreeIntegrity> {\n const resolvedRoot = resolve(root);\n const entries = await collectFiles(resolvedRoot, resolvedRoot);\n const hash = createHash(\"sha256\");\n let bytes = 0;\n for (const entry of entries) {\n const contents = await readFile(entry.absolutePath);\n bytes += contents.length;\n hash.update(entry.relativePath);\n hash.update(\"\\0\");\n hash.update(String(contents.length));\n hash.update(\"\\0\");\n hash.update(contents);\n hash.update(\"\\0\");\n }\n return {\n path: manifestPath,\n files: entries.length,\n bytes,\n sha256: hash.digest(\"hex\"),\n };\n}\n\nasync function collectFiles(\n root: string,\n directory: string,\n): Promise<Array<{ readonly absolutePath: string; readonly relativePath: string }>> {\n const output: Array<{ absolutePath: string; relativePath: string }> = [];\n for (const name of (await readdir(directory)).sort()) {\n const absolutePath = join(directory, name);\n const linkInfo = await lstat(absolutePath);\n const info = linkInfo.isSymbolicLink() ? await stat(absolutePath) : linkInfo;\n if (info.isDirectory()) {\n if (linkInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency tree contains a directory symlink: ${absolutePath}`);\n }\n output.push(...(await collectFiles(root, absolutePath)));\n continue;\n }\n if (!info.isFile()) {\n throw new Error(`Runtime dependency tree contains an unsupported entry: ${absolutePath}`);\n }\n if (linkInfo.isSymbolicLink()) {\n const target = await realpath(absolutePath);\n if (target !== root && !target.startsWith(`${root}${sep}`)) {\n throw new Error(\n `Runtime dependency tree contains an external file symlink: ${absolutePath}`,\n );\n }\n }\n const relativePath = relative(root, absolutePath).split(sep).join(\"/\");\n if (relativePath.length === 0 || relativePath.startsWith(\"../\")) {\n throw new Error(`Runtime dependency path escapes its root: ${absolutePath}`);\n }\n output.push({ absolutePath, relativePath });\n }\n return output.sort((left, right) => left.relativePath.localeCompare(right.relativePath));\n}\n", "import { homedir, tmpdir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nexport interface FleetPaths {\n readonly runtimeRoot: string;\n readonly stateRoot: string;\n readonly socketPath: string;\n readonly databasePath: string;\n}\n\nexport function resolveApplicationRoot(env: NodeJS.ProcessEnv = process.env): string {\n return (\n env.PIFLEET_APPLICATION_ROOT ??\n (process.platform === \"darwin\"\n ? join(homedir(), \"Library\", \"Application Support\", \"Pi Fleet\", \"runtime\")\n : join(env.XDG_DATA_HOME ?? join(homedir(), \".local\", \"share\"), \"pi-fleet\"))\n );\n}\n\nexport function resolveFleetPaths(env: NodeJS.ProcessEnv = process.env): FleetPaths {\n const explicitRoot = env.PIFLEET_STATE_ROOT;\n if (explicitRoot !== undefined) {\n const root = resolve(explicitRoot);\n return {\n runtimeRoot: root,\n stateRoot: root,\n socketPath: join(root, \"control.sock\"),\n databasePath: join(root, \"fleet.sqlite\"),\n };\n }\n\n const runtimeRoot = join(\n env.XDG_RUNTIME_DIR ?? tmpdir(),\n `pifleet-${process.getuid?.() ?? \"user\"}`,\n );\n const stateRoot =\n process.platform === \"darwin\"\n ? join(homedir(), \"Library\", \"Application Support\", \"Pi Fleet\")\n : join(env.XDG_STATE_HOME ?? join(homedir(), \".local\", \"state\"), \"pi-fleet\");\n return {\n runtimeRoot,\n stateRoot,\n socketPath: join(runtimeRoot, \"control.sock\"),\n databasePath: join(stateRoot, \"fleet.sqlite\"),\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["dirname", "join", "createHash", "chmod", "lstat", "mkdir", "readFile", "rename", "rm", "writeFile", "join", "resolve", "sep", "readFile", "join", "resolve", "readFile", "join", "createHash", "mkdir", "writeFile", "chmod", "rename", "rm", "lstat", "sep", "homedir", "join", "resolve", "dirname", "join"]
|
|
7
7
|
}
|