agl 1.0.17 → 21.0.2
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/.smartconfig.json +55 -0
- package/changelog.md +1026 -0
- package/cli.js +14 -0
- package/dist_serve/bundle.js +44778 -0
- package/dist_serve/index.html +13 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.authmodels.d.ts +126 -0
- package/dist_ts/classes.authmodels.js +1422 -0
- package/dist_ts/classes.authstore.d.ts +160 -0
- package/dist_ts/classes.authstore.js +2483 -0
- package/dist_ts/classes.browserresourcehost.d.ts +85 -0
- package/dist_ts/classes.browserresourcehost.js +912 -0
- package/dist_ts/classes.cli.d.ts +21 -0
- package/dist_ts/classes.cli.js +1082 -0
- package/dist_ts/classes.config.d.ts +23 -0
- package/dist_ts/classes.config.js +267 -0
- package/dist_ts/classes.controller.d.ts +523 -0
- package/dist_ts/classes.controller.js +10611 -0
- package/dist_ts/classes.controllermanagement.d.ts +32 -0
- package/dist_ts/classes.controllermanagement.js +222 -0
- package/dist_ts/classes.draftmanager.d.ts +30 -0
- package/dist_ts/classes.draftmanager.js +179 -0
- package/dist_ts/classes.embeddeddb.d.ts +30 -0
- package/dist_ts/classes.embeddeddb.js +159 -0
- package/dist_ts/classes.flexframedtransport.d.ts +56 -0
- package/dist_ts/classes.flexframedtransport.js +275 -0
- package/dist_ts/classes.flexmodels.private.d.ts +231 -0
- package/dist_ts/classes.flexmodels.private.js +985 -0
- package/dist_ts/classes.flexmodels.public.d.ts +207 -0
- package/dist_ts/classes.flexmodels.public.js +885 -0
- package/dist_ts/classes.flexprojectionreader.d.ts +89 -0
- package/dist_ts/classes.flexprojectionreader.js +580 -0
- package/dist_ts/classes.flexservice.d.ts +196 -0
- package/dist_ts/classes.flexservice.js +3704 -0
- package/dist_ts/classes.flexstore.d.ts +174 -0
- package/dist_ts/classes.flexstore.js +3400 -0
- package/dist_ts/classes.flexsupervisor.d.ts +105 -0
- package/dist_ts/classes.flexsupervisor.js +1191 -0
- package/dist_ts/classes.gitreversion.d.ts +431 -0
- package/dist_ts/classes.gitreversion.js +10592 -0
- package/dist_ts/classes.harnessoperationmanager.d.ts +113 -0
- package/dist_ts/classes.harnessoperationmanager.js +602 -0
- package/dist_ts/classes.opencodeclient.d.ts +146 -0
- package/dist_ts/classes.opencodeclient.js +3003 -0
- package/dist_ts/classes.opencodesupervisor.d.ts +60 -0
- package/dist_ts/classes.opencodesupervisor.js +1003 -0
- package/dist_ts/classes.passkeymanager.d.ts +34 -0
- package/dist_ts/classes.passkeymanager.js +456 -0
- package/dist_ts/classes.processinspection.d.ts +50 -0
- package/dist_ts/classes.processinspection.js +484 -0
- package/dist_ts/classes.resourcecoordinator.d.ts +64 -0
- package/dist_ts/classes.resourcecoordinator.js +294 -0
- package/dist_ts/classes.sessionintelligencereader.d.ts +13 -0
- package/dist_ts/classes.sessionintelligencereader.js +40 -0
- package/dist_ts/classes.systemmetricssampler.d.ts +53 -0
- package/dist_ts/classes.systemmetricssampler.js +168 -0
- package/dist_ts/classes.terminalmanager.d.ts +95 -0
- package/dist_ts/classes.terminalmanager.js +981 -0
- package/dist_ts/classes.terminalresourcehost.d.ts +20 -0
- package/dist_ts/classes.terminalresourcehost.js +84 -0
- package/dist_ts/classes.upgradecoordinator.d.ts +244 -0
- package/dist_ts/classes.upgradecoordinator.js +2155 -0
- package/dist_ts/classes.upgradetransaction.d.ts +92 -0
- package/dist_ts/classes.upgradetransaction.js +2125 -0
- package/dist_ts/classes.uploadmanager.d.ts +24 -0
- package/dist_ts/classes.uploadmanager.js +210 -0
- package/dist_ts/classes.validation.d.ts +91 -0
- package/dist_ts/classes.validation.js +1087 -0
- package/dist_ts/flexharness.child.d.ts +1 -0
- package/dist_ts/flexharness.child.js +28 -0
- package/dist_ts/functions.canonicaldirectory.d.ts +21 -0
- package/dist_ts/functions.canonicaldirectory.js +144 -0
- package/dist_ts/functions.controllerdataroot.d.ts +15 -0
- package/dist_ts/functions.controllerdataroot.js +76 -0
- package/dist_ts/functions.embeddeddb.d.ts +2 -0
- package/dist_ts/functions.embeddeddb.js +21 -0
- package/dist_ts/functions.flexcredentialstore.d.ts +16 -0
- package/dist_ts/functions.flexcredentialstore.js +93 -0
- package/dist_ts/functions.opencodeauth.d.ts +3 -0
- package/dist_ts/functions.opencodeauth.js +31 -0
- package/dist_ts/functions.runtimeenvironment.d.ts +2 -0
- package/dist_ts/functions.runtimeenvironment.js +79 -0
- package/dist_ts/functions.upgradefollower.d.ts +3 -0
- package/dist_ts/functions.upgradefollower.js +95 -0
- package/dist_ts/index.d.ts +24 -0
- package/dist_ts/index.js +25 -0
- package/dist_ts/interfaces.auth.d.ts +181 -0
- package/dist_ts/interfaces.auth.js +82 -0
- package/dist_ts/interfaces.config.d.ts +34 -0
- package/dist_ts/interfaces.config.js +2 -0
- package/dist_ts/interfaces.flexipc.d.ts +939 -0
- package/dist_ts/interfaces.flexipc.js +1492 -0
- package/dist_ts/interfaces.gitreversion.d.ts +246 -0
- package/dist_ts/interfaces.gitreversion.js +2 -0
- package/dist_ts/interfaces.lifecycle.d.ts +37 -0
- package/dist_ts/interfaces.lifecycle.js +2 -0
- package/dist_ts/interfaces.opencode.d.ts +101 -0
- package/dist_ts/interfaces.opencode.js +3 -0
- package/dist_ts/interfaces.projects.d.ts +156 -0
- package/dist_ts/interfaces.projects.js +5 -0
- package/dist_ts/plugins.d.ts +36 -0
- package/dist_ts/plugins.js +40 -0
- package/dist_ts_interfaces/index.d.ts +2 -0
- package/dist_ts_interfaces/index.js +3 -0
- package/dist_ts_interfaces/interfaces.d.ts +747 -0
- package/dist_ts_interfaces/interfaces.js +47 -0
- package/dist_ts_interfaces/plugins.d.ts +4 -0
- package/dist_ts_interfaces/plugins.js +3 -0
- package/dist_ts_interfaces/requests.d.ts +806 -0
- package/dist_ts_interfaces/requests.js +2 -0
- package/dist_ts_migration/classes.documentmigrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.documentmigrationrunner.js +24 -0
- package/dist_ts_migration/classes.flexmigrationrunner.d.ts +11 -0
- package/dist_ts_migration/classes.flexmigrationrunner.js +25 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.d.ts +10 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.js +15 -0
- package/dist_ts_migration/classes.migrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.migrationrunner.js +34 -0
- package/dist_ts_migration/index.d.ts +12 -0
- package/dist_ts_migration/index.js +13 -0
- package/dist_ts_migration/v10_flexharnessv3migration.d.ts +11 -0
- package/dist_ts_migration/v10_flexharnessv3migration.js +23 -0
- package/dist_ts_migration/v13_flexprojectionorder.d.ts +11 -0
- package/dist_ts_migration/v13_flexprojectionorder.js +23 -0
- package/dist_ts_migration/v16_flexprovidercredentials.d.ts +22 -0
- package/dist_ts_migration/v16_flexprovidercredentials.js +149 -0
- package/dist_ts_migration/v18_resourcelayout.d.ts +22 -0
- package/dist_ts_migration/v18_resourcelayout.js +23 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.d.ts +6 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.js +61 -0
- package/dist_ts_migration/v19_flexprojectmanagement.d.ts +11 -0
- package/dist_ts_migration/v19_flexprojectmanagement.js +21 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.d.ts +28 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.js +415 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.d.ts +7 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.js +105 -0
- package/dist_ts_migration/v2_controllerdataroot.d.ts +130 -0
- package/dist_ts_migration/v2_controllerdataroot.js +1887 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.js +100 -0
- package/dist_ts_migration/v6_protocoldocuments.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocuments.js +138 -0
- package/html/index.html +13 -0
- package/{LICENSE → license.md} +2 -2
- package/package.json +86 -48
- package/readme.md +480 -0
- package/readme.plan.md +188 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.authmodels.ts +1245 -0
- package/ts/classes.authstore.ts +3274 -0
- package/ts/classes.browserresourcehost.ts +1205 -0
- package/ts/classes.cli.ts +1254 -0
- package/ts/classes.config.ts +351 -0
- package/ts/classes.controller.ts +14426 -0
- package/ts/classes.controllermanagement.ts +330 -0
- package/ts/classes.draftmanager.ts +232 -0
- package/ts/classes.embeddeddb.ts +166 -0
- package/ts/classes.flexframedtransport.ts +283 -0
- package/ts/classes.flexmodels.private.ts +823 -0
- package/ts/classes.flexmodels.public.ts +732 -0
- package/ts/classes.flexprojectionreader.ts +816 -0
- package/ts/classes.flexservice.ts +4302 -0
- package/ts/classes.flexstore.ts +4565 -0
- package/ts/classes.flexsupervisor.ts +1453 -0
- package/ts/classes.gitreversion.ts +13353 -0
- package/ts/classes.harnessoperationmanager.ts +870 -0
- package/ts/classes.opencodeclient.ts +4110 -0
- package/ts/classes.opencodesupervisor.ts +1280 -0
- package/ts/classes.passkeymanager.ts +570 -0
- package/ts/classes.processinspection.ts +623 -0
- package/ts/classes.resourcecoordinator.ts +436 -0
- package/ts/classes.sessionintelligencereader.ts +52 -0
- package/ts/classes.systemmetricssampler.ts +215 -0
- package/ts/classes.terminalmanager.ts +1207 -0
- package/ts/classes.terminalresourcehost.ts +122 -0
- package/ts/classes.upgradecoordinator.ts +2675 -0
- package/ts/classes.upgradetransaction.ts +2900 -0
- package/ts/classes.uploadmanager.ts +240 -0
- package/ts/classes.validation.ts +1409 -0
- package/ts/flexharness.child.ts +35 -0
- package/ts/functions.canonicaldirectory.ts +213 -0
- package/ts/functions.controllerdataroot.ts +107 -0
- package/ts/functions.embeddeddb.ts +22 -0
- package/ts/functions.flexcredentialstore.ts +128 -0
- package/ts/functions.opencodeauth.ts +34 -0
- package/ts/functions.runtimeenvironment.ts +90 -0
- package/ts/functions.upgradefollower.ts +115 -0
- package/ts/index.ts +36 -6
- package/ts/interfaces.auth.ts +316 -0
- package/ts/interfaces.config.ts +37 -0
- package/ts/interfaces.flexipc.ts +2586 -0
- package/ts/interfaces.gitreversion.ts +336 -0
- package/ts/interfaces.lifecycle.ts +46 -0
- package/ts/interfaces.opencode.ts +153 -0
- package/ts/interfaces.projects.ts +182 -0
- package/ts/plugins.ts +64 -0
- package/ts_interfaces/index.ts +2 -0
- package/ts_interfaces/interfaces.ts +827 -0
- package/ts_interfaces/plugins.ts +15 -0
- package/ts_interfaces/requests.ts +1186 -0
- package/ts_migration/classes.documentmigrationrunner.ts +32 -0
- package/ts_migration/classes.flexmigrationrunner.ts +33 -0
- package/ts_migration/classes.flexpostharnessmigrationrunner.ts +22 -0
- package/ts_migration/classes.migrationrunner.ts +40 -0
- package/ts_migration/index.ts +12 -0
- package/ts_migration/v10_flexharnessv3migration.ts +35 -0
- package/ts_migration/v13_flexprojectionorder.ts +33 -0
- package/ts_migration/v16_flexprovidercredentials.ts +196 -0
- package/ts_migration/v18_resourcelayout.ts +55 -0
- package/ts_migration/v18_resourcelayoutmigration.ts +68 -0
- package/ts_migration/v19_flexprojectmanagement.ts +28 -0
- package/ts_migration/v1_embeddeddatabaselocation.ts +560 -0
- package/ts_migration/v22_projectfilesystemidentitymigration.ts +121 -0
- package/ts_migration/v2_controllerdataroot.ts +2349 -0
- package/ts_migration/v6_protocoldocumentmigration.ts +144 -0
- package/ts_migration/v6_protocoldocuments.ts +198 -0
- package/ts_web/00_commitinfo_data.ts +8 -0
- package/ts_web/classes.controllersocketclient.ts +517 -0
- package/ts_web/classes.sessiondraftsync.ts +390 -0
- package/ts_web/elements.harnesscontrollerapp.ts +11494 -0
- package/ts_web/index.ts +2 -0
- package/ts_web/plugins.ts +31 -0
- package/.gitlab-ci.yml +0 -71
- package/.npmignore +0 -5
- package/README.md +0 -40
- package/dist/cli.js +0 -2
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -9
- package/dist/mod_bundle/index.d.ts +0 -1
- package/dist/mod_bundle/index.js +0 -18
- package/dist/mod_bundle/mod.plugins.d.ts +0 -4
- package/dist/mod_bundle/mod.plugins.js +0 -11
- package/dist/mod_install/index.d.ts +0 -4
- package/dist/mod_install/index.js +0 -21
- package/dist/mod_install/mod.plugins.d.ts +0 -1
- package/dist/mod_install/mod.plugins.js +0 -7
- package/dist/mod_standard/index.d.ts +0 -4
- package/dist/mod_standard/index.js +0 -21
- package/dist/mod_standard/mod.browser.d.ts +0 -6
- package/dist/mod_standard/mod.browser.js +0 -14
- package/dist/mod_standard/mod.clean.d.ts +0 -4
- package/dist/mod_standard/mod.clean.js +0 -12
- package/dist/mod_standard/mod.compile.d.ts +0 -4
- package/dist/mod_standard/mod.compile.js +0 -21
- package/dist/mod_standard/mod.plugins.d.ts +0 -8
- package/dist/mod_standard/mod.plugins.js +0 -19
- package/dist/mod_standard/mod.test.d.ts +0 -4
- package/dist/mod_standard/mod.test.js +0 -12
- package/dist/plr.cli.d.ts +0 -3
- package/dist/plr.cli.js +0 -57
- package/dist/plr.config.d.ts +0 -11
- package/dist/plr.config.js +0 -26
- package/dist/plr.mods.d.ts +0 -17
- package/dist/plr.mods.js +0 -17
- package/dist/plr.paths.d.ts +0 -19
- package/dist/plr.paths.js +0 -26
- package/dist/plr.plugins.d.ts +0 -8
- package/dist/plr.plugins.js +0 -16
- package/npmextra.json +0 -10
- package/ts/mod_bundle/index.ts +0 -20
- package/ts/mod_bundle/mod.plugins.ts +0 -9
- package/ts/mod_install/index.ts +0 -20
- package/ts/mod_install/mod.plugins.ts +0 -1
- package/ts/mod_standard/index.ts +0 -23
- package/ts/mod_standard/mod.browser.ts +0 -17
- package/ts/mod_standard/mod.clean.ts +0 -13
- package/ts/mod_standard/mod.compile.ts +0 -23
- package/ts/mod_standard/mod.plugins.ts +0 -17
- package/ts/mod_standard/mod.test.ts +0 -13
- package/ts/plr.cli.ts +0 -60
- package/ts/plr.config.ts +0 -36
- package/ts/plr.mods.ts +0 -25
- package/ts/plr.paths.ts +0 -29
- package/ts/plr.plugins.ts +0 -17
- package/tslint.json +0 -3
- package/yarn.lock +0 -3464
|
@@ -0,0 +1,2155 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { controllerPackageName, } from '../dist_ts_interfaces/index.js';
|
|
3
|
+
import { processIdentityHasCliCommand, readControllerProcessIdentity, readProcessGroupMemberPids, } from './classes.processinspection.js';
|
|
4
|
+
export const upgradeCoordinationVersion = 2;
|
|
5
|
+
const coordinationVersion = upgradeCoordinationVersion;
|
|
6
|
+
export const upgradePackageTransitionTransactionVersion = 3;
|
|
7
|
+
export const upgradePackageTransitionSource = {
|
|
8
|
+
packageName: '@modelprofile.com/harness-controller',
|
|
9
|
+
version: '20.0.3',
|
|
10
|
+
managementVersion: 1,
|
|
11
|
+
cliName: 'hcon',
|
|
12
|
+
cliRelativePath: './cli.js',
|
|
13
|
+
};
|
|
14
|
+
export const upgradePackageTransitionTarget = {
|
|
15
|
+
packageName: 'agl',
|
|
16
|
+
version: '21.0.0',
|
|
17
|
+
managementVersion: 2,
|
|
18
|
+
cliName: 'agl',
|
|
19
|
+
cliRelativePath: './cli.js',
|
|
20
|
+
};
|
|
21
|
+
const currentCliName = String(controllerPackageName) === upgradePackageTransitionSource.packageName
|
|
22
|
+
? upgradePackageTransitionSource.cliName
|
|
23
|
+
: upgradePackageTransitionTarget.cliName;
|
|
24
|
+
const ownerFileName = 'owner.json';
|
|
25
|
+
const maximumMetadataBytes = 256 * 1024;
|
|
26
|
+
const initializationGraceMs = 30_000;
|
|
27
|
+
const startLeaseDrainTimeoutMs = 60_000;
|
|
28
|
+
const upgradeTokenPattern = /^[A-Za-z0-9_-]{43}$/;
|
|
29
|
+
const upgradeTokenHashPattern = /^[a-f0-9]{64}$/;
|
|
30
|
+
const leaseDirectoryPattern = /^[a-f0-9]{20}$/;
|
|
31
|
+
const tokenMetadataPattern = /^(?:grant|ack|action-(?:prepare|finalize))-[a-f0-9]{20}\.json(?:\.consuming-[1-9][0-9]*-[a-f0-9]{8})?$/;
|
|
32
|
+
const transactionMetadataPattern = /^transaction-[a-f0-9]{20}\.json$/;
|
|
33
|
+
const transactionTemporaryMetadataPattern = /^transaction-[a-f0-9]{20}\.json\.tmp-[1-9][0-9]*-[a-f0-9]{8}$/;
|
|
34
|
+
const transactionMutationDirectoryPattern = /^transaction-[a-f0-9]{20}\.json\.lock$/;
|
|
35
|
+
const ownershipGuardDirectoryPattern = /^[a-f0-9]{64}\.guard$/;
|
|
36
|
+
const tokenMetadataRetentionMs = 10 * 60 * 1000;
|
|
37
|
+
const transactionRetentionMs = 24 * 60 * 60 * 1000;
|
|
38
|
+
const terminalStatusRetentionMs = 10 * 60 * 1000;
|
|
39
|
+
const transactionMutationTimeoutMs = 10_000;
|
|
40
|
+
const ownershipGuardTimeoutMs = 10_000;
|
|
41
|
+
const workerTerminationGraceMs = 5_000;
|
|
42
|
+
export const upgradeTokenEnvironmentVariable = 'HARNESS_CONTROLLER_UPGRADE_TOKEN';
|
|
43
|
+
const assertUid = () => {
|
|
44
|
+
if (typeof process.getuid !== 'function') {
|
|
45
|
+
throw new Error(`${currentCliName} upgrade requires a POSIX effective user identity.`);
|
|
46
|
+
}
|
|
47
|
+
const uid = process.getuid();
|
|
48
|
+
if (!Number.isSafeInteger(uid) || uid < 0) {
|
|
49
|
+
throw new Error('The effective user identity is invalid.');
|
|
50
|
+
}
|
|
51
|
+
return uid;
|
|
52
|
+
};
|
|
53
|
+
const assertToken = (tokenArg) => {
|
|
54
|
+
if (typeof tokenArg !== 'string' || !upgradeTokenPattern.test(tokenArg)) {
|
|
55
|
+
throw new Error('The upgrade coordination token is invalid.');
|
|
56
|
+
}
|
|
57
|
+
return tokenArg;
|
|
58
|
+
};
|
|
59
|
+
const hashToken = (tokenArg) => plugins.crypto
|
|
60
|
+
.createHash('sha256')
|
|
61
|
+
.update(assertToken(tokenArg), 'utf8')
|
|
62
|
+
.digest('hex');
|
|
63
|
+
const tokensEqual = (leftArg, rightArg) => {
|
|
64
|
+
const left = Buffer.from(leftArg, 'utf8');
|
|
65
|
+
const right = Buffer.from(rightArg, 'utf8');
|
|
66
|
+
return left.byteLength === right.byteLength && plugins.crypto.timingSafeEqual(left, right);
|
|
67
|
+
};
|
|
68
|
+
const assertPort = (portArg) => {
|
|
69
|
+
if (!Number.isSafeInteger(portArg) || portArg < 1 || portArg > 65_535) {
|
|
70
|
+
throw new Error('The upgrade coordination port is invalid.');
|
|
71
|
+
}
|
|
72
|
+
return portArg;
|
|
73
|
+
};
|
|
74
|
+
const exactKeys = (valueArg, expectedArg) => {
|
|
75
|
+
const actual = Object.keys(valueArg).sort();
|
|
76
|
+
const expected = [...expectedArg].sort();
|
|
77
|
+
return actual.length === expected.length
|
|
78
|
+
&& actual.every((key, index) => key === expected[index]);
|
|
79
|
+
};
|
|
80
|
+
const assertPrivateDirectory = async (directoryArg) => {
|
|
81
|
+
const stats = await plugins.fs.promises.lstat(directoryArg);
|
|
82
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
83
|
+
throw new Error(`Upgrade coordination path must be a real directory: ${directoryArg}`);
|
|
84
|
+
}
|
|
85
|
+
if (typeof process.getuid === 'function' && stats.uid !== process.getuid()) {
|
|
86
|
+
throw new Error(`Upgrade coordination path is not owned by the current user: ${directoryArg}`);
|
|
87
|
+
}
|
|
88
|
+
if ((stats.mode & 0o077) !== 0) {
|
|
89
|
+
throw new Error(`Upgrade coordination path must not be group or world accessible: ${directoryArg}`);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const lstatIfPresent = async (filePathArg) => {
|
|
93
|
+
try {
|
|
94
|
+
return await plugins.fs.promises.lstat(filePathArg);
|
|
95
|
+
}
|
|
96
|
+
catch (errorArg) {
|
|
97
|
+
if (errorArg.code === 'ENOENT')
|
|
98
|
+
return undefined;
|
|
99
|
+
throw errorArg;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const ensurePrivateDirectory = async (directoryArg) => {
|
|
103
|
+
try {
|
|
104
|
+
await plugins.fs.promises.mkdir(directoryArg, { mode: 0o700 });
|
|
105
|
+
}
|
|
106
|
+
catch (errorArg) {
|
|
107
|
+
if (errorArg.code !== 'EEXIST')
|
|
108
|
+
throw errorArg;
|
|
109
|
+
}
|
|
110
|
+
await assertPrivateDirectory(directoryArg);
|
|
111
|
+
};
|
|
112
|
+
const syncDirectory = async (directoryArg) => {
|
|
113
|
+
const handle = await plugins.fs.promises.open(directoryArg, plugins.fs.constants.O_RDONLY);
|
|
114
|
+
try {
|
|
115
|
+
await handle.sync();
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
await handle.close();
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const writePrivateJson = async (filePathArg, valueArg, exclusiveArg = true) => {
|
|
122
|
+
const flags = plugins.fs.constants.O_WRONLY
|
|
123
|
+
| plugins.fs.constants.O_CREAT
|
|
124
|
+
| plugins.fs.constants.O_NOFOLLOW
|
|
125
|
+
| (exclusiveArg ? plugins.fs.constants.O_EXCL : plugins.fs.constants.O_TRUNC);
|
|
126
|
+
const handle = await plugins.fs.promises.open(filePathArg, flags, 0o600);
|
|
127
|
+
try {
|
|
128
|
+
await handle.writeFile(`${JSON.stringify(valueArg)}\n`, 'utf8');
|
|
129
|
+
await handle.sync();
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
await handle.close();
|
|
133
|
+
}
|
|
134
|
+
await syncDirectory(plugins.path.dirname(filePathArg));
|
|
135
|
+
};
|
|
136
|
+
const readPrivateJson = async (filePathArg) => {
|
|
137
|
+
const handle = await plugins.fs.promises.open(filePathArg, plugins.fs.constants.O_RDONLY | plugins.fs.constants.O_NOFOLLOW);
|
|
138
|
+
try {
|
|
139
|
+
const stats = await handle.stat();
|
|
140
|
+
if (!stats.isFile() || stats.size < 2 || stats.size > maximumMetadataBytes) {
|
|
141
|
+
throw new Error(`Upgrade coordination metadata is not a bounded regular file: ${filePathArg}`);
|
|
142
|
+
}
|
|
143
|
+
if (typeof process.getuid === 'function' && stats.uid !== process.getuid()) {
|
|
144
|
+
throw new Error(`Upgrade coordination metadata is not owned by the current user: ${filePathArg}`);
|
|
145
|
+
}
|
|
146
|
+
if ((stats.mode & 0o077) !== 0) {
|
|
147
|
+
throw new Error(`Upgrade coordination metadata is not private: ${filePathArg}`);
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
return JSON.parse(await handle.readFile('utf8'));
|
|
151
|
+
}
|
|
152
|
+
catch (errorArg) {
|
|
153
|
+
const error = new Error(`Upgrade coordination metadata is malformed: ${filePathArg}`, {
|
|
154
|
+
cause: errorArg,
|
|
155
|
+
});
|
|
156
|
+
error.code = 'HCON_INVALID_JSON';
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
await handle.close();
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
const parseOwner = (valueArg) => {
|
|
165
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
166
|
+
throw new Error('Upgrade owner metadata is malformed.');
|
|
167
|
+
}
|
|
168
|
+
const value = valueArg;
|
|
169
|
+
if (!exactKeys(value, [
|
|
170
|
+
'version',
|
|
171
|
+
'kind',
|
|
172
|
+
'uid',
|
|
173
|
+
'tokenHash',
|
|
174
|
+
'pid',
|
|
175
|
+
'processGroupId',
|
|
176
|
+
'fingerprint',
|
|
177
|
+
'cliPath',
|
|
178
|
+
'command',
|
|
179
|
+
'createdAt',
|
|
180
|
+
])) {
|
|
181
|
+
throw new Error('Upgrade owner metadata has unexpected fields.');
|
|
182
|
+
}
|
|
183
|
+
if (value.version !== coordinationVersion
|
|
184
|
+
|| (value.kind !== 'upgrade' && value.kind !== 'start')
|
|
185
|
+
|| !Number.isSafeInteger(value.uid)
|
|
186
|
+
|| value.uid < 0
|
|
187
|
+
|| !Number.isSafeInteger(value.pid)
|
|
188
|
+
|| value.pid < 2
|
|
189
|
+
|| !Number.isSafeInteger(value.processGroupId)
|
|
190
|
+
|| value.processGroupId < 2
|
|
191
|
+
|| !Number.isSafeInteger(value.createdAt)
|
|
192
|
+
|| value.createdAt < 1
|
|
193
|
+
|| typeof value.fingerprint !== 'string'
|
|
194
|
+
|| value.fingerprint.length < 8
|
|
195
|
+
|| value.fingerprint.length > 256
|
|
196
|
+
|| typeof value.cliPath !== 'string'
|
|
197
|
+
|| !plugins.path.isAbsolute(value.cliPath)
|
|
198
|
+
|| (value.command !== '__serve'
|
|
199
|
+
&& value.command !== '__upgrade-worker'
|
|
200
|
+
&& value.command !== 'start'
|
|
201
|
+
&& value.command !== 'upgrade'
|
|
202
|
+
&& value.command !== 'foreground'
|
|
203
|
+
&& value.command !== 'temp-password')) {
|
|
204
|
+
throw new Error('Upgrade owner metadata is invalid.');
|
|
205
|
+
}
|
|
206
|
+
if (typeof value.tokenHash !== 'string' || !upgradeTokenHashPattern.test(value.tokenHash)) {
|
|
207
|
+
throw new Error('Upgrade owner metadata token binding is invalid.');
|
|
208
|
+
}
|
|
209
|
+
if ((value.kind === 'upgrade'
|
|
210
|
+
&& value.command !== '__serve'
|
|
211
|
+
&& value.command !== '__upgrade-worker'
|
|
212
|
+
&& value.command !== 'upgrade')
|
|
213
|
+
|| (value.kind === 'start' && value.command === '__upgrade-worker')) {
|
|
214
|
+
throw new Error('Upgrade owner metadata kind and command do not match.');
|
|
215
|
+
}
|
|
216
|
+
return value;
|
|
217
|
+
};
|
|
218
|
+
const parseExpectedController = (valueArg) => {
|
|
219
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
220
|
+
throw new Error('The expected controller identity is malformed.');
|
|
221
|
+
}
|
|
222
|
+
const value = valueArg;
|
|
223
|
+
if (!exactKeys(value, ['pid', 'processGroupId', 'processFingerprint'])
|
|
224
|
+
|| !Number.isSafeInteger(value.pid)
|
|
225
|
+
|| value.pid < 2
|
|
226
|
+
|| !Number.isSafeInteger(value.processGroupId)
|
|
227
|
+
|| value.processGroupId < 2
|
|
228
|
+
|| typeof value.processFingerprint !== 'string'
|
|
229
|
+
|| value.processFingerprint.length < 8
|
|
230
|
+
|| value.processFingerprint.length > 256) {
|
|
231
|
+
throw new Error('The expected controller identity is invalid.');
|
|
232
|
+
}
|
|
233
|
+
return value;
|
|
234
|
+
};
|
|
235
|
+
const assertBoundedText = (valueArg, nameArg, maximumBytesArg) => {
|
|
236
|
+
if (typeof valueArg !== 'string'
|
|
237
|
+
|| valueArg.length === 0
|
|
238
|
+
|| Buffer.byteLength(valueArg, 'utf8') > maximumBytesArg) {
|
|
239
|
+
throw new Error(`${nameArg} is invalid.`);
|
|
240
|
+
}
|
|
241
|
+
return valueArg;
|
|
242
|
+
};
|
|
243
|
+
const assertRuntimeId = (valueArg) => {
|
|
244
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
245
|
+
throw new Error('The upgrade session identity is malformed.');
|
|
246
|
+
}
|
|
247
|
+
const value = valueArg;
|
|
248
|
+
if (!exactKeys(value, ['harnessId', 'nativeId'])
|
|
249
|
+
|| (value.harnessId !== 'opencode' && value.harnessId !== 'flex'))
|
|
250
|
+
throw new Error('The upgrade session identity is invalid.');
|
|
251
|
+
return {
|
|
252
|
+
harnessId: value.harnessId,
|
|
253
|
+
nativeId: assertBoundedText(value.nativeId, 'The upgrade native session ID', 512),
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
const sessionTransitionStates = new Set([
|
|
257
|
+
'pending',
|
|
258
|
+
'submitting',
|
|
259
|
+
'accepted',
|
|
260
|
+
'paused',
|
|
261
|
+
'outcomeUnknown',
|
|
262
|
+
'failed',
|
|
263
|
+
]);
|
|
264
|
+
const parseUpgradeSessionState = (valueArg) => {
|
|
265
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
266
|
+
throw new Error('Upgrade session state is malformed.');
|
|
267
|
+
}
|
|
268
|
+
const value = valueArg;
|
|
269
|
+
if (!exactKeys(value, [
|
|
270
|
+
'projectId',
|
|
271
|
+
'sessionId',
|
|
272
|
+
'pauseState',
|
|
273
|
+
...(value.pauseQueueId === undefined ? [] : ['pauseQueueId']),
|
|
274
|
+
...(value.cleanupState === undefined ? [] : ['cleanupState']),
|
|
275
|
+
...(value.continueState === undefined ? [] : ['continueState']),
|
|
276
|
+
...(value.error === undefined ? [] : ['error']),
|
|
277
|
+
]))
|
|
278
|
+
throw new Error('Upgrade session state has unexpected fields.');
|
|
279
|
+
if (typeof value.pauseState !== 'string'
|
|
280
|
+
|| !sessionTransitionStates.has(value.pauseState)
|
|
281
|
+
|| (value.cleanupState !== undefined && (typeof value.cleanupState !== 'string' || !sessionTransitionStates.has(value.cleanupState)))
|
|
282
|
+
|| (value.continueState !== undefined && (typeof value.continueState !== 'string' || !sessionTransitionStates.has(value.continueState))))
|
|
283
|
+
throw new Error('Upgrade session transition state is invalid.');
|
|
284
|
+
const sessionId = assertRuntimeId(value.sessionId);
|
|
285
|
+
if (value.pauseQueueId !== undefined && sessionId.harnessId !== 'flex') {
|
|
286
|
+
throw new Error('Only Flex upgrade sessions may retain a pause queue ID.');
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
projectId: assertBoundedText(value.projectId, 'The upgrade project ID', 512),
|
|
290
|
+
sessionId,
|
|
291
|
+
pauseState: value.pauseState,
|
|
292
|
+
...(value.pauseQueueId === undefined
|
|
293
|
+
? {}
|
|
294
|
+
: { pauseQueueId: assertBoundedText(value.pauseQueueId, 'The Flex pause queue ID', 512) }),
|
|
295
|
+
...(value.cleanupState === undefined
|
|
296
|
+
? {}
|
|
297
|
+
: { cleanupState: value.cleanupState }),
|
|
298
|
+
...(value.continueState === undefined
|
|
299
|
+
? {}
|
|
300
|
+
: { continueState: value.continueState }),
|
|
301
|
+
...(value.error === undefined
|
|
302
|
+
? {}
|
|
303
|
+
: { error: assertBoundedText(value.error, 'The upgrade session error', 2_048) }),
|
|
304
|
+
};
|
|
305
|
+
};
|
|
306
|
+
const transactionPhases = new Set([
|
|
307
|
+
'starting',
|
|
308
|
+
'checking',
|
|
309
|
+
'preparing',
|
|
310
|
+
'pausing',
|
|
311
|
+
'stopping',
|
|
312
|
+
'installing',
|
|
313
|
+
'restarting',
|
|
314
|
+
'continuing',
|
|
315
|
+
'completed',
|
|
316
|
+
'failed',
|
|
317
|
+
]);
|
|
318
|
+
const transactionPhaseOrder = {
|
|
319
|
+
starting: 0,
|
|
320
|
+
checking: 1,
|
|
321
|
+
preparing: 2,
|
|
322
|
+
pausing: 3,
|
|
323
|
+
stopping: 4,
|
|
324
|
+
installing: 5,
|
|
325
|
+
restarting: 6,
|
|
326
|
+
continuing: 7,
|
|
327
|
+
completed: 8,
|
|
328
|
+
failed: 8,
|
|
329
|
+
};
|
|
330
|
+
const parseUpgradeTransactionV2 = (valueArg) => {
|
|
331
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
332
|
+
throw new Error('Upgrade transaction metadata is malformed.');
|
|
333
|
+
}
|
|
334
|
+
const value = valueArg;
|
|
335
|
+
if (!exactKeys(value, [
|
|
336
|
+
'version', 'tokenHash', 'revision', 'port', 'sourceVersion', 'controllerWasRunning',
|
|
337
|
+
'continueSessions', 'gracePeriodMs', 'phase', 'message', 'createdAt', 'updatedAt',
|
|
338
|
+
'phaseStartedAt', 'sessions',
|
|
339
|
+
...(value.targetVersion === undefined ? [] : ['targetVersion']),
|
|
340
|
+
...(value.targetStartupInvoked === undefined ? [] : ['targetStartupInvoked']),
|
|
341
|
+
...(value.preparationAcceptedAt === undefined ? [] : ['preparationAcceptedAt']),
|
|
342
|
+
...(value.preparationDeadlineAt === undefined ? [] : ['preparationDeadlineAt']),
|
|
343
|
+
...(value.preparationCompletedAt === undefined ? [] : ['preparationCompletedAt']),
|
|
344
|
+
...(value.retainedUntil === undefined ? [] : ['retainedUntil']),
|
|
345
|
+
...(value.worker === undefined ? [] : ['worker']),
|
|
346
|
+
...(value.controller === undefined ? [] : ['controller']),
|
|
347
|
+
...(value.terminal === undefined ? [] : ['terminal']),
|
|
348
|
+
]))
|
|
349
|
+
throw new Error('Upgrade transaction metadata has unexpected fields.');
|
|
350
|
+
if (value.version !== coordinationVersion
|
|
351
|
+
|| typeof value.tokenHash !== 'string'
|
|
352
|
+
|| !upgradeTokenHashPattern.test(value.tokenHash)
|
|
353
|
+
|| !Number.isSafeInteger(value.revision)
|
|
354
|
+
|| value.revision < 0
|
|
355
|
+
|| typeof value.controllerWasRunning !== 'boolean'
|
|
356
|
+
|| (value.targetStartupInvoked !== undefined && value.targetStartupInvoked !== true)
|
|
357
|
+
|| typeof value.continueSessions !== 'boolean'
|
|
358
|
+
|| !Number.isSafeInteger(value.gracePeriodMs)
|
|
359
|
+
|| value.gracePeriodMs < 1_000
|
|
360
|
+
|| value.gracePeriodMs > 60 * 60 * 1000
|
|
361
|
+
|| ((value.preparationAcceptedAt === undefined)
|
|
362
|
+
!== (value.preparationDeadlineAt === undefined))
|
|
363
|
+
|| (value.preparationAcceptedAt !== undefined && (!Number.isSafeInteger(value.preparationAcceptedAt)
|
|
364
|
+
|| value.preparationAcceptedAt < value.createdAt
|
|
365
|
+
|| value.preparationAcceptedAt > value.updatedAt
|
|
366
|
+
|| !Number.isSafeInteger(value.preparationDeadlineAt)
|
|
367
|
+
|| value.preparationDeadlineAt
|
|
368
|
+
!== value.preparationAcceptedAt + value.gracePeriodMs))
|
|
369
|
+
|| (value.preparationCompletedAt !== undefined && (value.preparationAcceptedAt === undefined
|
|
370
|
+
|| !Number.isSafeInteger(value.preparationCompletedAt)
|
|
371
|
+
|| value.preparationCompletedAt < value.preparationAcceptedAt
|
|
372
|
+
|| value.preparationCompletedAt > value.preparationDeadlineAt
|
|
373
|
+
|| typeof value.phase !== 'string'
|
|
374
|
+
|| (transactionPhaseOrder[value.phase] ?? -1)
|
|
375
|
+
< transactionPhaseOrder.stopping))
|
|
376
|
+
|| typeof value.phase !== 'string'
|
|
377
|
+
|| !transactionPhases.has(value.phase)
|
|
378
|
+
|| !Number.isSafeInteger(value.createdAt)
|
|
379
|
+
|| value.createdAt < 1
|
|
380
|
+
|| !Number.isSafeInteger(value.updatedAt)
|
|
381
|
+
|| value.updatedAt < value.createdAt
|
|
382
|
+
|| !Number.isSafeInteger(value.phaseStartedAt)
|
|
383
|
+
|| value.phaseStartedAt < value.createdAt
|
|
384
|
+
|| value.phaseStartedAt > value.updatedAt
|
|
385
|
+
|| (value.retainedUntil !== undefined && (!Number.isSafeInteger(value.retainedUntil)
|
|
386
|
+
|| value.retainedUntil < value.updatedAt))
|
|
387
|
+
|| !Array.isArray(value.sessions)
|
|
388
|
+
|| value.sessions.length > 64)
|
|
389
|
+
throw new Error('Upgrade transaction metadata is invalid.');
|
|
390
|
+
let worker;
|
|
391
|
+
if (value.worker !== undefined) {
|
|
392
|
+
if (!value.worker || typeof value.worker !== 'object' || Array.isArray(value.worker)) {
|
|
393
|
+
throw new Error('Upgrade worker metadata is malformed.');
|
|
394
|
+
}
|
|
395
|
+
const rawWorker = value.worker;
|
|
396
|
+
if (!exactKeys(rawWorker, [
|
|
397
|
+
'pid', 'processGroupId', 'fingerprint', 'cliPath',
|
|
398
|
+
...(rawWorker.logFilePath === undefined ? [] : ['logFilePath']),
|
|
399
|
+
])
|
|
400
|
+
|| !Number.isSafeInteger(rawWorker.pid)
|
|
401
|
+
|| rawWorker.pid < 2
|
|
402
|
+
|| !Number.isSafeInteger(rawWorker.processGroupId)
|
|
403
|
+
|| rawWorker.processGroupId < 2
|
|
404
|
+
|| typeof rawWorker.cliPath !== 'string'
|
|
405
|
+
|| !plugins.path.isAbsolute(rawWorker.cliPath))
|
|
406
|
+
throw new Error('Upgrade worker metadata is invalid.');
|
|
407
|
+
worker = {
|
|
408
|
+
pid: rawWorker.pid,
|
|
409
|
+
processGroupId: rawWorker.processGroupId,
|
|
410
|
+
fingerprint: assertBoundedText(rawWorker.fingerprint, 'The upgrade worker fingerprint', 256),
|
|
411
|
+
cliPath: rawWorker.cliPath,
|
|
412
|
+
...(rawWorker.logFilePath === undefined
|
|
413
|
+
? {}
|
|
414
|
+
: {
|
|
415
|
+
logFilePath: assertBoundedText(rawWorker.logFilePath, 'The upgrade worker log path', 4_096),
|
|
416
|
+
}),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
let terminal;
|
|
420
|
+
if (value.terminal !== undefined) {
|
|
421
|
+
if (!value.terminal || typeof value.terminal !== 'object' || Array.isArray(value.terminal)) {
|
|
422
|
+
throw new Error('Upgrade terminal metadata is malformed.');
|
|
423
|
+
}
|
|
424
|
+
const rawTerminal = value.terminal;
|
|
425
|
+
if (!exactKeys(rawTerminal, ['success', ...(rawTerminal.error === undefined ? [] : ['error'])])
|
|
426
|
+
|| typeof rawTerminal.success !== 'boolean')
|
|
427
|
+
throw new Error('Upgrade terminal metadata is invalid.');
|
|
428
|
+
terminal = {
|
|
429
|
+
success: rawTerminal.success,
|
|
430
|
+
...(rawTerminal.error === undefined
|
|
431
|
+
? {}
|
|
432
|
+
: { error: assertBoundedText(rawTerminal.error, 'The upgrade terminal error', 4_096) }),
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
let controller;
|
|
436
|
+
if (value.controller !== undefined) {
|
|
437
|
+
if (!value.controller || typeof value.controller !== 'object' || Array.isArray(value.controller)) {
|
|
438
|
+
throw new Error('Upgrade controller metadata is malformed.');
|
|
439
|
+
}
|
|
440
|
+
const rawController = value.controller;
|
|
441
|
+
if (!exactKeys(rawController, [
|
|
442
|
+
'pid', 'processGroupId', 'fingerprint', 'cliPath', 'command',
|
|
443
|
+
])
|
|
444
|
+
|| !Number.isSafeInteger(rawController.pid)
|
|
445
|
+
|| rawController.pid < 2
|
|
446
|
+
|| !Number.isSafeInteger(rawController.processGroupId)
|
|
447
|
+
|| rawController.processGroupId < 2
|
|
448
|
+
|| typeof rawController.cliPath !== 'string'
|
|
449
|
+
|| !plugins.path.isAbsolute(rawController.cliPath)
|
|
450
|
+
|| (rawController.command !== '__serve' && rawController.command !== 'foreground'))
|
|
451
|
+
throw new Error('Upgrade controller metadata is invalid.');
|
|
452
|
+
controller = {
|
|
453
|
+
pid: rawController.pid,
|
|
454
|
+
processGroupId: rawController.processGroupId,
|
|
455
|
+
fingerprint: assertBoundedText(rawController.fingerprint, 'The upgrade controller fingerprint', 256),
|
|
456
|
+
cliPath: rawController.cliPath,
|
|
457
|
+
command: rawController.command,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
return {
|
|
461
|
+
version: coordinationVersion,
|
|
462
|
+
tokenHash: value.tokenHash,
|
|
463
|
+
revision: value.revision,
|
|
464
|
+
port: assertPort(value.port),
|
|
465
|
+
sourceVersion: assertBoundedText(value.sourceVersion, 'The upgrade source version', 128),
|
|
466
|
+
...(value.targetVersion === undefined
|
|
467
|
+
? {}
|
|
468
|
+
: { targetVersion: assertBoundedText(value.targetVersion, 'The upgrade target version', 128) }),
|
|
469
|
+
...(value.targetStartupInvoked === true ? { targetStartupInvoked: true } : {}),
|
|
470
|
+
controllerWasRunning: value.controllerWasRunning,
|
|
471
|
+
continueSessions: value.continueSessions,
|
|
472
|
+
gracePeriodMs: value.gracePeriodMs,
|
|
473
|
+
...(value.preparationAcceptedAt === undefined
|
|
474
|
+
? {}
|
|
475
|
+
: {
|
|
476
|
+
preparationAcceptedAt: value.preparationAcceptedAt,
|
|
477
|
+
preparationDeadlineAt: value.preparationDeadlineAt,
|
|
478
|
+
}),
|
|
479
|
+
...(value.preparationCompletedAt === undefined
|
|
480
|
+
? {}
|
|
481
|
+
: { preparationCompletedAt: value.preparationCompletedAt }),
|
|
482
|
+
phase: value.phase,
|
|
483
|
+
message: assertBoundedText(value.message, 'The upgrade transaction message', 4_096),
|
|
484
|
+
createdAt: value.createdAt,
|
|
485
|
+
phaseStartedAt: value.phaseStartedAt,
|
|
486
|
+
updatedAt: value.updatedAt,
|
|
487
|
+
...(value.retainedUntil === undefined
|
|
488
|
+
? {}
|
|
489
|
+
: { retainedUntil: value.retainedUntil }),
|
|
490
|
+
...(worker ? { worker } : {}),
|
|
491
|
+
...(controller ? { controller } : {}),
|
|
492
|
+
sessions: value.sessions.map(parseUpgradeSessionState),
|
|
493
|
+
...(terminal ? { terminal } : {}),
|
|
494
|
+
};
|
|
495
|
+
};
|
|
496
|
+
const parseUpgradeTransactionV3 = (valueArg) => {
|
|
497
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
498
|
+
throw new Error('Upgrade transaction metadata is malformed.');
|
|
499
|
+
}
|
|
500
|
+
const value = valueArg;
|
|
501
|
+
if (!exactKeys(value, [
|
|
502
|
+
'version', 'tokenHash', 'revision', 'port',
|
|
503
|
+
'sourcePackageName', 'sourceVersion', 'sourceManagementVersion',
|
|
504
|
+
'sourceCliName', 'sourceCliRelativePath',
|
|
505
|
+
'targetPackageName', 'targetVersion', 'targetManagementVersion',
|
|
506
|
+
'targetCliName', 'targetCliRelativePath',
|
|
507
|
+
'controllerWasRunning', 'continueSessions', 'gracePeriodMs', 'phase', 'message',
|
|
508
|
+
'createdAt', 'updatedAt', 'phaseStartedAt', 'sessions',
|
|
509
|
+
...(value.packageTransitionStarted === undefined ? [] : ['packageTransitionStarted']),
|
|
510
|
+
...(value.groupedTargetVerified === undefined ? [] : ['groupedTargetVerified']),
|
|
511
|
+
...(value.targetPackageCommitStarted === undefined ? [] : ['targetPackageCommitStarted']),
|
|
512
|
+
...(value.targetPackageCommitted === undefined ? [] : ['targetPackageCommitted']),
|
|
513
|
+
...(value.targetStartupInvoked === undefined ? [] : ['targetStartupInvoked']),
|
|
514
|
+
...(value.preparationAcceptedAt === undefined ? [] : ['preparationAcceptedAt']),
|
|
515
|
+
...(value.preparationDeadlineAt === undefined ? [] : ['preparationDeadlineAt']),
|
|
516
|
+
...(value.preparationCompletedAt === undefined ? [] : ['preparationCompletedAt']),
|
|
517
|
+
...(value.retainedUntil === undefined ? [] : ['retainedUntil']),
|
|
518
|
+
...(value.worker === undefined ? [] : ['worker']),
|
|
519
|
+
...(value.controller === undefined ? [] : ['controller']),
|
|
520
|
+
...(value.terminal === undefined ? [] : ['terminal']),
|
|
521
|
+
]))
|
|
522
|
+
throw new Error('Upgrade transaction metadata has unexpected fields.');
|
|
523
|
+
if (value.version !== upgradePackageTransitionTransactionVersion
|
|
524
|
+
|| value.sourcePackageName !== upgradePackageTransitionSource.packageName
|
|
525
|
+
|| value.sourceVersion !== upgradePackageTransitionSource.version
|
|
526
|
+
|| value.sourceManagementVersion !== upgradePackageTransitionSource.managementVersion
|
|
527
|
+
|| value.sourceCliName !== upgradePackageTransitionSource.cliName
|
|
528
|
+
|| value.sourceCliRelativePath !== upgradePackageTransitionSource.cliRelativePath
|
|
529
|
+
|| value.targetPackageName !== upgradePackageTransitionTarget.packageName
|
|
530
|
+
|| value.targetVersion !== upgradePackageTransitionTarget.version
|
|
531
|
+
|| value.targetManagementVersion !== upgradePackageTransitionTarget.managementVersion
|
|
532
|
+
|| value.targetCliName !== upgradePackageTransitionTarget.cliName
|
|
533
|
+
|| value.targetCliRelativePath !== upgradePackageTransitionTarget.cliRelativePath
|
|
534
|
+
|| (value.packageTransitionStarted !== undefined && value.packageTransitionStarted !== true)
|
|
535
|
+
|| (value.groupedTargetVerified !== undefined && value.groupedTargetVerified !== true)
|
|
536
|
+
|| (value.targetPackageCommitStarted !== undefined
|
|
537
|
+
&& value.targetPackageCommitStarted !== true)
|
|
538
|
+
|| (value.targetPackageCommitted !== undefined && value.targetPackageCommitted !== true)
|
|
539
|
+
|| (value.targetStartupInvoked !== undefined && value.targetStartupInvoked !== true))
|
|
540
|
+
throw new Error('Upgrade package-transition identity or checkpoint metadata is invalid.');
|
|
541
|
+
if ((value.groupedTargetVerified === true && value.packageTransitionStarted !== true)
|
|
542
|
+
|| (value.targetPackageCommitStarted === true && value.groupedTargetVerified !== true)
|
|
543
|
+
|| (value.targetPackageCommitted === true && value.targetPackageCommitStarted !== true)
|
|
544
|
+
|| (value.targetStartupInvoked === true && value.targetPackageCommitted !== true)
|
|
545
|
+
|| (value.targetStartupInvoked === true && value.controllerWasRunning !== true))
|
|
546
|
+
throw new Error('Upgrade package-transition checkpoints violate their implication chain.');
|
|
547
|
+
const compatible = parseUpgradeTransactionV2({
|
|
548
|
+
version: coordinationVersion,
|
|
549
|
+
tokenHash: value.tokenHash,
|
|
550
|
+
revision: value.revision,
|
|
551
|
+
port: value.port,
|
|
552
|
+
sourceVersion: value.sourceVersion,
|
|
553
|
+
targetVersion: value.targetVersion,
|
|
554
|
+
...(value.targetStartupInvoked === true ? { targetStartupInvoked: true } : {}),
|
|
555
|
+
controllerWasRunning: value.controllerWasRunning,
|
|
556
|
+
continueSessions: value.continueSessions,
|
|
557
|
+
gracePeriodMs: value.gracePeriodMs,
|
|
558
|
+
...(value.preparationAcceptedAt === undefined
|
|
559
|
+
? {}
|
|
560
|
+
: {
|
|
561
|
+
preparationAcceptedAt: value.preparationAcceptedAt,
|
|
562
|
+
preparationDeadlineAt: value.preparationDeadlineAt,
|
|
563
|
+
}),
|
|
564
|
+
...(value.preparationCompletedAt === undefined
|
|
565
|
+
? {}
|
|
566
|
+
: { preparationCompletedAt: value.preparationCompletedAt }),
|
|
567
|
+
phase: value.phase,
|
|
568
|
+
message: value.message,
|
|
569
|
+
createdAt: value.createdAt,
|
|
570
|
+
phaseStartedAt: value.phaseStartedAt,
|
|
571
|
+
updatedAt: value.updatedAt,
|
|
572
|
+
...(value.retainedUntil === undefined ? {} : { retainedUntil: value.retainedUntil }),
|
|
573
|
+
...(value.worker === undefined ? {} : { worker: value.worker }),
|
|
574
|
+
...(value.controller === undefined ? {} : { controller: value.controller }),
|
|
575
|
+
sessions: value.sessions,
|
|
576
|
+
...(value.terminal === undefined ? {} : { terminal: value.terminal }),
|
|
577
|
+
});
|
|
578
|
+
if (compatible.terminal?.success === true
|
|
579
|
+
&& (value.targetPackageCommitted !== true
|
|
580
|
+
|| (compatible.controllerWasRunning && value.targetStartupInvoked !== true)
|
|
581
|
+
|| (!compatible.controllerWasRunning && value.targetStartupInvoked === true)))
|
|
582
|
+
throw new Error('A successful package transition is missing its terminal checkpoint.');
|
|
583
|
+
return {
|
|
584
|
+
...compatible,
|
|
585
|
+
version: upgradePackageTransitionTransactionVersion,
|
|
586
|
+
sourcePackageName: upgradePackageTransitionSource.packageName,
|
|
587
|
+
sourceVersion: upgradePackageTransitionSource.version,
|
|
588
|
+
sourceManagementVersion: upgradePackageTransitionSource.managementVersion,
|
|
589
|
+
sourceCliName: upgradePackageTransitionSource.cliName,
|
|
590
|
+
sourceCliRelativePath: upgradePackageTransitionSource.cliRelativePath,
|
|
591
|
+
targetPackageName: upgradePackageTransitionTarget.packageName,
|
|
592
|
+
targetVersion: upgradePackageTransitionTarget.version,
|
|
593
|
+
targetManagementVersion: upgradePackageTransitionTarget.managementVersion,
|
|
594
|
+
targetCliName: upgradePackageTransitionTarget.cliName,
|
|
595
|
+
targetCliRelativePath: upgradePackageTransitionTarget.cliRelativePath,
|
|
596
|
+
...(value.packageTransitionStarted === true ? { packageTransitionStarted: true } : {}),
|
|
597
|
+
...(value.groupedTargetVerified === true ? { groupedTargetVerified: true } : {}),
|
|
598
|
+
...(value.targetPackageCommitStarted === true ? { targetPackageCommitStarted: true } : {}),
|
|
599
|
+
...(value.targetPackageCommitted === true ? { targetPackageCommitted: true } : {}),
|
|
600
|
+
...(value.targetStartupInvoked === true ? { targetStartupInvoked: true } : {}),
|
|
601
|
+
};
|
|
602
|
+
};
|
|
603
|
+
const parseUpgradeTransaction = (valueArg) => {
|
|
604
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
605
|
+
throw new Error('Upgrade transaction metadata is malformed.');
|
|
606
|
+
}
|
|
607
|
+
return valueArg.version === coordinationVersion
|
|
608
|
+
? parseUpgradeTransactionV2(valueArg)
|
|
609
|
+
: parseUpgradeTransactionV3(valueArg);
|
|
610
|
+
};
|
|
611
|
+
const parseTransactionMutationOwner = (valueArg) => {
|
|
612
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
613
|
+
throw new Error('The upgrade transaction mutation owner is malformed.');
|
|
614
|
+
}
|
|
615
|
+
const value = valueArg;
|
|
616
|
+
if (!exactKeys(value, [
|
|
617
|
+
'version', 'uid', 'tokenHash', 'pid', 'fingerprint', 'nonce', 'createdAt',
|
|
618
|
+
])
|
|
619
|
+
|| value.version !== coordinationVersion
|
|
620
|
+
|| !Number.isSafeInteger(value.uid)
|
|
621
|
+
|| value.uid < 0
|
|
622
|
+
|| typeof value.tokenHash !== 'string'
|
|
623
|
+
|| !upgradeTokenHashPattern.test(value.tokenHash)
|
|
624
|
+
|| !Number.isSafeInteger(value.pid)
|
|
625
|
+
|| value.pid < 2
|
|
626
|
+
|| typeof value.nonce !== 'string'
|
|
627
|
+
|| !/^[a-f0-9]{32}$/.test(value.nonce)
|
|
628
|
+
|| !Number.isSafeInteger(value.createdAt)
|
|
629
|
+
|| value.createdAt < 1)
|
|
630
|
+
throw new Error('The upgrade transaction mutation owner is invalid.');
|
|
631
|
+
return {
|
|
632
|
+
version: coordinationVersion,
|
|
633
|
+
uid: value.uid,
|
|
634
|
+
tokenHash: value.tokenHash,
|
|
635
|
+
pid: value.pid,
|
|
636
|
+
fingerprint: assertBoundedText(value.fingerprint, 'The upgrade transaction mutation fingerprint', 256),
|
|
637
|
+
nonce: value.nonce,
|
|
638
|
+
createdAt: value.createdAt,
|
|
639
|
+
};
|
|
640
|
+
};
|
|
641
|
+
const parseOwnershipMutationGuardOwner = (valueArg) => {
|
|
642
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
643
|
+
throw new Error('The upgrade ownership mutation guard is malformed.');
|
|
644
|
+
}
|
|
645
|
+
const value = valueArg;
|
|
646
|
+
if (!exactKeys(value, [
|
|
647
|
+
'version', 'uid', 'targetHash', 'pid', 'fingerprint', 'nonce', 'createdAt',
|
|
648
|
+
])
|
|
649
|
+
|| value.version !== coordinationVersion
|
|
650
|
+
|| !Number.isSafeInteger(value.uid)
|
|
651
|
+
|| value.uid < 0
|
|
652
|
+
|| typeof value.targetHash !== 'string'
|
|
653
|
+
|| !upgradeTokenHashPattern.test(value.targetHash)
|
|
654
|
+
|| !Number.isSafeInteger(value.pid)
|
|
655
|
+
|| value.pid < 2
|
|
656
|
+
|| typeof value.nonce !== 'string'
|
|
657
|
+
|| !/^[a-f0-9]{32}$/.test(value.nonce)
|
|
658
|
+
|| !Number.isSafeInteger(value.createdAt)
|
|
659
|
+
|| value.createdAt < 1)
|
|
660
|
+
throw new Error('The upgrade ownership mutation guard is invalid.');
|
|
661
|
+
return {
|
|
662
|
+
version: coordinationVersion,
|
|
663
|
+
uid: value.uid,
|
|
664
|
+
targetHash: value.targetHash,
|
|
665
|
+
pid: value.pid,
|
|
666
|
+
fingerprint: assertBoundedText(value.fingerprint, 'The upgrade ownership mutation guard fingerprint', 256),
|
|
667
|
+
nonce: value.nonce,
|
|
668
|
+
createdAt: value.createdAt,
|
|
669
|
+
};
|
|
670
|
+
};
|
|
671
|
+
export const upgradeTransactionIsStalled = (transactionArg, nowArg = Date.now()) => {
|
|
672
|
+
if (transactionArg.terminal)
|
|
673
|
+
return false;
|
|
674
|
+
if (transactionArg.preparationDeadlineAt !== undefined
|
|
675
|
+
&& transactionArg.preparationCompletedAt === undefined
|
|
676
|
+
&& (transactionArg.phase === 'preparing' || transactionArg.phase === 'pausing'))
|
|
677
|
+
return nowArg > transactionArg.preparationDeadlineAt + 60_000;
|
|
678
|
+
const maximumPhaseDurationMs = {
|
|
679
|
+
starting: 2 * 60 * 1000,
|
|
680
|
+
checking: 3 * 60 * 1000,
|
|
681
|
+
preparing: transactionArg.gracePeriodMs + 60_000,
|
|
682
|
+
pausing: transactionArg.gracePeriodMs + 60_000,
|
|
683
|
+
stopping: 90_000,
|
|
684
|
+
installing: 22 * 60 * 1000,
|
|
685
|
+
restarting: 3 * 60 * 1000,
|
|
686
|
+
continuing: 2 * 60 * 1000,
|
|
687
|
+
completed: Number.MAX_SAFE_INTEGER,
|
|
688
|
+
failed: Number.MAX_SAFE_INTEGER,
|
|
689
|
+
};
|
|
690
|
+
return nowArg - transactionArg.phaseStartedAt > maximumPhaseDurationMs[transactionArg.phase];
|
|
691
|
+
};
|
|
692
|
+
const ownerIsLive = async (ownerArg) => {
|
|
693
|
+
if (ownerArg.uid !== assertUid())
|
|
694
|
+
return false;
|
|
695
|
+
const identity = await readControllerProcessIdentity(ownerArg.pid);
|
|
696
|
+
if (identity && identity.fingerprint === ownerArg.fingerprint) {
|
|
697
|
+
return await processIdentityHasCliCommand(identity, ownerArg.cliPath, ownerArg.command, { allowMissingAbsolutePath: true });
|
|
698
|
+
}
|
|
699
|
+
if (ownerArg.kind !== 'upgrade' || ownerArg.processGroupId !== ownerArg.pid)
|
|
700
|
+
return false;
|
|
701
|
+
return (await readProcessGroupMemberPids(ownerArg.processGroupId))
|
|
702
|
+
.some((processIdArg) => processIdArg !== ownerArg.pid);
|
|
703
|
+
};
|
|
704
|
+
const ownerForCurrentProcess = async (kindArg, tokenArg, cliPathArg, commandArg) => {
|
|
705
|
+
const identity = await readControllerProcessIdentity(process.pid);
|
|
706
|
+
if (!identity)
|
|
707
|
+
throw new Error('Unable to establish upgrade process ownership.');
|
|
708
|
+
return {
|
|
709
|
+
version: coordinationVersion,
|
|
710
|
+
kind: kindArg,
|
|
711
|
+
uid: assertUid(),
|
|
712
|
+
tokenHash: hashToken(tokenArg),
|
|
713
|
+
pid: process.pid,
|
|
714
|
+
processGroupId: identity.processGroupId,
|
|
715
|
+
fingerprint: identity.fingerprint,
|
|
716
|
+
cliPath: cliPathArg,
|
|
717
|
+
command: commandArg,
|
|
718
|
+
createdAt: Date.now(),
|
|
719
|
+
};
|
|
720
|
+
};
|
|
721
|
+
const coordinationPathHash = (valueArg) => plugins.crypto
|
|
722
|
+
.createHash('sha256')
|
|
723
|
+
.update(valueArg)
|
|
724
|
+
.digest('hex')
|
|
725
|
+
.slice(0, 20);
|
|
726
|
+
const ownershipTargetHash = (valueArg) => plugins.crypto
|
|
727
|
+
.createHash('sha256')
|
|
728
|
+
.update(valueArg)
|
|
729
|
+
.digest('hex');
|
|
730
|
+
const sameOwnedDirectoryIdentity = (statsArg, identityArg) => statsArg.dev === identityArg.dev && statsArg.ino === identityArg.ino;
|
|
731
|
+
const exactPrimitiveRecordMatches = (leftArg, rightArg) => {
|
|
732
|
+
const left = leftArg;
|
|
733
|
+
const right = rightArg;
|
|
734
|
+
const keys = Object.keys(left);
|
|
735
|
+
return exactKeys(right, keys) && keys.every((keyArg) => left[keyArg] === right[keyArg]);
|
|
736
|
+
};
|
|
737
|
+
const removeExactOwnedDirectory = async (directoryArg, expectationArg) => {
|
|
738
|
+
const initialStats = await plugins.fs.promises.lstat(directoryArg);
|
|
739
|
+
if (!sameOwnedDirectoryIdentity(initialStats, expectationArg.identity)) {
|
|
740
|
+
throw new Error('Upgrade coordination ownership changed before removal.');
|
|
741
|
+
}
|
|
742
|
+
const entries = await plugins.fs.promises.readdir(directoryArg, { withFileTypes: true });
|
|
743
|
+
if (entries.length > 1
|
|
744
|
+
|| entries.some((entryArg) => (entryArg.name !== ownerFileName
|
|
745
|
+
|| !entryArg.isFile()
|
|
746
|
+
|| entryArg.isSymbolicLink())))
|
|
747
|
+
throw new Error(`Upgrade coordination owner directory contains unsafe entries: ${directoryArg}`);
|
|
748
|
+
if (Boolean(entries.length) !== Boolean(expectationArg.assertOwner)) {
|
|
749
|
+
throw new Error('Upgrade coordination ownership changed before removal.');
|
|
750
|
+
}
|
|
751
|
+
if (entries.length === 1) {
|
|
752
|
+
const ownerPath = plugins.path.join(directoryArg, ownerFileName);
|
|
753
|
+
const tombstonePath = plugins.path.join(directoryArg, `.owner-removing-${process.pid}-${plugins.crypto.randomBytes(8).toString('hex')}`);
|
|
754
|
+
expectationArg.assertRemovalAuthorized?.();
|
|
755
|
+
await plugins.fs.promises.rename(ownerPath, tombstonePath);
|
|
756
|
+
try {
|
|
757
|
+
expectationArg.assertOwner(await readPrivateJson(tombstonePath));
|
|
758
|
+
}
|
|
759
|
+
catch (errorArg) {
|
|
760
|
+
let restoreError;
|
|
761
|
+
try {
|
|
762
|
+
await plugins.fs.promises.link(tombstonePath, ownerPath);
|
|
763
|
+
await plugins.fs.promises.unlink(tombstonePath);
|
|
764
|
+
await syncDirectory(directoryArg);
|
|
765
|
+
}
|
|
766
|
+
catch (restoreErrorArg) {
|
|
767
|
+
restoreError = restoreErrorArg;
|
|
768
|
+
}
|
|
769
|
+
if (restoreError !== undefined) {
|
|
770
|
+
throw new AggregateError([errorArg, restoreError], 'Upgrade coordination ownership changed and could not be restored safely.');
|
|
771
|
+
}
|
|
772
|
+
throw errorArg;
|
|
773
|
+
}
|
|
774
|
+
await plugins.fs.promises.unlink(tombstonePath);
|
|
775
|
+
await syncDirectory(directoryArg);
|
|
776
|
+
}
|
|
777
|
+
const currentStats = await lstatIfPresent(directoryArg);
|
|
778
|
+
if (!currentStats || !sameOwnedDirectoryIdentity(currentStats, expectationArg.identity))
|
|
779
|
+
return;
|
|
780
|
+
try {
|
|
781
|
+
await plugins.fs.promises.rmdir(directoryArg);
|
|
782
|
+
}
|
|
783
|
+
catch (errorArg) {
|
|
784
|
+
const code = errorArg.code;
|
|
785
|
+
if (code === 'ENOENT')
|
|
786
|
+
return;
|
|
787
|
+
if (code === 'ENOTEMPTY' || code === 'EEXIST') {
|
|
788
|
+
throw new Error('Upgrade coordination ownership changed during removal.', {
|
|
789
|
+
cause: errorArg,
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
throw errorArg;
|
|
793
|
+
}
|
|
794
|
+
await syncDirectory(plugins.path.dirname(directoryArg));
|
|
795
|
+
};
|
|
796
|
+
class UpgradeOwnershipMutationGuard {
|
|
797
|
+
directory;
|
|
798
|
+
owner;
|
|
799
|
+
released = false;
|
|
800
|
+
releaseTask;
|
|
801
|
+
constructor(directory, owner) {
|
|
802
|
+
this.directory = directory;
|
|
803
|
+
this.owner = owner;
|
|
804
|
+
}
|
|
805
|
+
release() {
|
|
806
|
+
if (this.released)
|
|
807
|
+
return Promise.resolve();
|
|
808
|
+
if (!this.releaseTask) {
|
|
809
|
+
let task;
|
|
810
|
+
task = (async () => {
|
|
811
|
+
const stats = await plugins.fs.promises.lstat(this.directory);
|
|
812
|
+
const owner = parseOwnershipMutationGuardOwner(await readPrivateJson(plugins.path.join(this.directory, ownerFileName)));
|
|
813
|
+
if (!exactPrimitiveRecordMatches(owner, this.owner)) {
|
|
814
|
+
throw new Error('Upgrade ownership mutation guard changed unexpectedly.');
|
|
815
|
+
}
|
|
816
|
+
await removeExactOwnedDirectory(this.directory, {
|
|
817
|
+
identity: { dev: stats.dev, ino: stats.ino },
|
|
818
|
+
assertOwner: (valueArg) => {
|
|
819
|
+
const removedOwner = parseOwnershipMutationGuardOwner(valueArg);
|
|
820
|
+
if (!exactPrimitiveRecordMatches(removedOwner, this.owner)) {
|
|
821
|
+
throw new Error('Upgrade ownership mutation guard changed during release.');
|
|
822
|
+
}
|
|
823
|
+
},
|
|
824
|
+
});
|
|
825
|
+
this.released = true;
|
|
826
|
+
})().finally(() => {
|
|
827
|
+
if (this.releaseTask === task && !this.released)
|
|
828
|
+
this.releaseTask = undefined;
|
|
829
|
+
});
|
|
830
|
+
this.releaseTask = task;
|
|
831
|
+
}
|
|
832
|
+
return this.releaseTask;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
class UpgradeOwnedDirectory {
|
|
836
|
+
directory;
|
|
837
|
+
owner;
|
|
838
|
+
releaseOwned;
|
|
839
|
+
released = false;
|
|
840
|
+
releaseTask;
|
|
841
|
+
constructor(directory, owner, releaseOwned) {
|
|
842
|
+
this.directory = directory;
|
|
843
|
+
this.owner = owner;
|
|
844
|
+
this.releaseOwned = releaseOwned;
|
|
845
|
+
}
|
|
846
|
+
async assertOwned() {
|
|
847
|
+
if (this.released)
|
|
848
|
+
throw new Error('Upgrade coordination ownership has already been released.');
|
|
849
|
+
let owner;
|
|
850
|
+
try {
|
|
851
|
+
owner = parseOwner(await readPrivateJson(plugins.path.join(this.directory, ownerFileName)));
|
|
852
|
+
}
|
|
853
|
+
catch (errorArg) {
|
|
854
|
+
if (errorArg.code === 'ENOENT') {
|
|
855
|
+
throw new Error('Upgrade coordination ownership changed unexpectedly.', { cause: errorArg });
|
|
856
|
+
}
|
|
857
|
+
throw errorArg;
|
|
858
|
+
}
|
|
859
|
+
if (!exactPrimitiveRecordMatches(owner, this.owner) || !await ownerIsLive(owner)) {
|
|
860
|
+
throw new Error('Upgrade coordination ownership changed unexpectedly.');
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
release(shouldReleaseArg) {
|
|
864
|
+
if (this.released)
|
|
865
|
+
return Promise.resolve();
|
|
866
|
+
if (!this.releaseTask) {
|
|
867
|
+
let task;
|
|
868
|
+
task = this.releaseOwned(this.directory, this.owner, shouldReleaseArg).then(() => {
|
|
869
|
+
this.released = true;
|
|
870
|
+
}).finally(() => {
|
|
871
|
+
if (this.releaseTask === task && !this.released)
|
|
872
|
+
this.releaseTask = undefined;
|
|
873
|
+
});
|
|
874
|
+
this.releaseTask = task;
|
|
875
|
+
}
|
|
876
|
+
return this.releaseTask;
|
|
877
|
+
}
|
|
878
|
+
relinquishAfterTransfer() {
|
|
879
|
+
if (this.released)
|
|
880
|
+
throw new Error('Upgrade coordination ownership has already been released.');
|
|
881
|
+
this.released = true;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
export class UpgradeInstallationLock extends UpgradeOwnedDirectory {
|
|
885
|
+
}
|
|
886
|
+
export class UpgradeStartLease extends UpgradeOwnedDirectory {
|
|
887
|
+
}
|
|
888
|
+
export class UpgradeCoordinator {
|
|
889
|
+
canonicalGlobalRoot;
|
|
890
|
+
uid;
|
|
891
|
+
baseDirectory;
|
|
892
|
+
upgradeLockDirectory;
|
|
893
|
+
startLeasesDirectory;
|
|
894
|
+
transactionsDirectory;
|
|
895
|
+
ownershipGuardsDirectory;
|
|
896
|
+
initializationTask;
|
|
897
|
+
constructor(canonicalGlobalRoot) {
|
|
898
|
+
this.canonicalGlobalRoot = canonicalGlobalRoot;
|
|
899
|
+
if (!plugins.path.isAbsolute(canonicalGlobalRoot)) {
|
|
900
|
+
throw new Error('The canonical pnpm global root must be absolute.');
|
|
901
|
+
}
|
|
902
|
+
this.uid = assertUid();
|
|
903
|
+
this.baseDirectory = plugins.path.join('/tmp', `harness-controller-upgrade-${this.uid}-${coordinationPathHash(canonicalGlobalRoot)}`);
|
|
904
|
+
this.upgradeLockDirectory = plugins.path.join(this.baseDirectory, 'upgrade.lock');
|
|
905
|
+
this.startLeasesDirectory = plugins.path.join(this.baseDirectory, 'start-leases');
|
|
906
|
+
this.transactionsDirectory = plugins.path.join(this.baseDirectory, 'transactions');
|
|
907
|
+
this.ownershipGuardsDirectory = plugins.path.join(this.baseDirectory, 'ownership-guards');
|
|
908
|
+
}
|
|
909
|
+
async init() {
|
|
910
|
+
if (!this.initializationTask) {
|
|
911
|
+
let task;
|
|
912
|
+
task = this.performInitialization().catch((errorArg) => {
|
|
913
|
+
if (this.initializationTask === task)
|
|
914
|
+
this.initializationTask = undefined;
|
|
915
|
+
throw errorArg;
|
|
916
|
+
});
|
|
917
|
+
this.initializationTask = task;
|
|
918
|
+
}
|
|
919
|
+
await this.initializationTask;
|
|
920
|
+
}
|
|
921
|
+
async performInitialization() {
|
|
922
|
+
await ensurePrivateDirectory(this.baseDirectory);
|
|
923
|
+
await ensurePrivateDirectory(this.startLeasesDirectory);
|
|
924
|
+
await ensurePrivateDirectory(this.transactionsDirectory);
|
|
925
|
+
await ensurePrivateDirectory(this.ownershipGuardsDirectory);
|
|
926
|
+
for (const entry of await plugins.fs.promises.readdir(this.ownershipGuardsDirectory, {
|
|
927
|
+
withFileTypes: true,
|
|
928
|
+
})) {
|
|
929
|
+
const guardPath = plugins.path.join(this.ownershipGuardsDirectory, entry.name);
|
|
930
|
+
if (!entry.isDirectory() || !ownershipGuardDirectoryPattern.test(entry.name)) {
|
|
931
|
+
throw new Error(`Upgrade ownership guard directory contains an unexpected entry: ${guardPath}`);
|
|
932
|
+
}
|
|
933
|
+
await assertPrivateDirectory(guardPath);
|
|
934
|
+
}
|
|
935
|
+
const entries = await plugins.fs.promises.readdir(this.baseDirectory, { withFileTypes: true });
|
|
936
|
+
for (const entry of entries) {
|
|
937
|
+
if (!entry.isFile() || !tokenMetadataPattern.test(entry.name))
|
|
938
|
+
continue;
|
|
939
|
+
const filePath = plugins.path.join(this.baseDirectory, entry.name);
|
|
940
|
+
const stats = await lstatIfPresent(filePath);
|
|
941
|
+
if (!stats)
|
|
942
|
+
continue;
|
|
943
|
+
if (!stats.isFile()
|
|
944
|
+
|| stats.isSymbolicLink()
|
|
945
|
+
|| stats.uid !== this.uid
|
|
946
|
+
|| (stats.mode & 0o077) !== 0) {
|
|
947
|
+
throw new Error(`Upgrade coordination metadata is unsafe: ${filePath}`);
|
|
948
|
+
}
|
|
949
|
+
if (Date.now() - stats.mtimeMs > tokenMetadataRetentionMs) {
|
|
950
|
+
await plugins.fs.promises.unlink(filePath).catch((errorArg) => {
|
|
951
|
+
if (errorArg.code !== 'ENOENT')
|
|
952
|
+
throw errorArg;
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
for (const entry of await plugins.fs.promises.readdir(this.transactionsDirectory, {
|
|
957
|
+
withFileTypes: true,
|
|
958
|
+
})) {
|
|
959
|
+
const filePath = plugins.path.join(this.transactionsDirectory, entry.name);
|
|
960
|
+
if (entry.isFile() && transactionTemporaryMetadataPattern.test(entry.name)) {
|
|
961
|
+
const stats = await lstatIfPresent(filePath);
|
|
962
|
+
if (!stats)
|
|
963
|
+
continue;
|
|
964
|
+
if (!stats.isFile()
|
|
965
|
+
|| stats.isSymbolicLink()
|
|
966
|
+
|| stats.uid !== this.uid
|
|
967
|
+
|| (stats.mode & 0o077) !== 0)
|
|
968
|
+
throw new Error(`Upgrade transaction temporary metadata is unsafe: ${filePath}`);
|
|
969
|
+
if (Date.now() - stats.mtimeMs > initializationGraceMs) {
|
|
970
|
+
await plugins.fs.promises.unlink(filePath).catch((errorArg) => {
|
|
971
|
+
if (errorArg.code !== 'ENOENT')
|
|
972
|
+
throw errorArg;
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
if (entry.isDirectory() && transactionMutationDirectoryPattern.test(entry.name)) {
|
|
978
|
+
const stats = await lstatIfPresent(filePath);
|
|
979
|
+
if (!stats)
|
|
980
|
+
continue;
|
|
981
|
+
if (!stats.isDirectory()
|
|
982
|
+
|| stats.isSymbolicLink()
|
|
983
|
+
|| stats.uid !== this.uid
|
|
984
|
+
|| (stats.mode & 0o077) !== 0)
|
|
985
|
+
throw new Error(`Upgrade transaction mutation metadata is unsafe: ${filePath}`);
|
|
986
|
+
if (Date.now() - stats.mtimeMs > transactionRetentionMs) {
|
|
987
|
+
await this.reclaimStaleTransactionMutationDirectory(filePath);
|
|
988
|
+
}
|
|
989
|
+
continue;
|
|
990
|
+
}
|
|
991
|
+
if (!entry.isFile() || !transactionMetadataPattern.test(entry.name))
|
|
992
|
+
continue;
|
|
993
|
+
const stats = await lstatIfPresent(filePath);
|
|
994
|
+
if (!stats)
|
|
995
|
+
continue;
|
|
996
|
+
if (!stats.isFile()
|
|
997
|
+
|| stats.isSymbolicLink()
|
|
998
|
+
|| stats.uid !== this.uid
|
|
999
|
+
|| (stats.mode & 0o077) !== 0)
|
|
1000
|
+
throw new Error(`Upgrade transaction metadata is unsafe: ${filePath}`);
|
|
1001
|
+
if (Date.now() - stats.mtimeMs > transactionRetentionMs) {
|
|
1002
|
+
const transaction = parseUpgradeTransaction(await readPrivateJson(filePath));
|
|
1003
|
+
const workerIsLive = await this.transactionWorkerIsLive(transaction).catch(() => true);
|
|
1004
|
+
const controllerIsLive = transaction.controller
|
|
1005
|
+
? await this.transactionControllerIsLive(transaction).catch(() => true)
|
|
1006
|
+
: false;
|
|
1007
|
+
if (transaction.terminal || (!workerIsLive && !controllerIsLive)) {
|
|
1008
|
+
await plugins.fs.promises.unlink(filePath).catch((errorArg) => {
|
|
1009
|
+
if (errorArg.code !== 'ENOENT')
|
|
1010
|
+
throw errorArg;
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
ownershipGuardDirectory(directoryArg) {
|
|
1017
|
+
return plugins.path.join(this.ownershipGuardsDirectory, `${ownershipTargetHash(directoryArg)}.guard`);
|
|
1018
|
+
}
|
|
1019
|
+
async acquireOwnershipMutationGuard(directoryArg) {
|
|
1020
|
+
const targetHash = ownershipTargetHash(directoryArg);
|
|
1021
|
+
const guardDirectory = this.ownershipGuardDirectory(directoryArg);
|
|
1022
|
+
const identity = await readControllerProcessIdentity(process.pid);
|
|
1023
|
+
if (!identity)
|
|
1024
|
+
throw new Error('Unable to establish upgrade ownership mutation guard identity.');
|
|
1025
|
+
const owner = {
|
|
1026
|
+
version: coordinationVersion,
|
|
1027
|
+
uid: this.uid,
|
|
1028
|
+
targetHash,
|
|
1029
|
+
pid: identity.pid,
|
|
1030
|
+
fingerprint: identity.fingerprint,
|
|
1031
|
+
nonce: plugins.crypto.randomBytes(16).toString('hex'),
|
|
1032
|
+
createdAt: Date.now(),
|
|
1033
|
+
};
|
|
1034
|
+
const deadline = Date.now() + ownershipGuardTimeoutMs;
|
|
1035
|
+
while (true) {
|
|
1036
|
+
try {
|
|
1037
|
+
await plugins.fs.promises.mkdir(guardDirectory, { mode: 0o700 });
|
|
1038
|
+
try {
|
|
1039
|
+
await writePrivateJson(plugins.path.join(guardDirectory, ownerFileName), owner);
|
|
1040
|
+
await syncDirectory(this.ownershipGuardsDirectory);
|
|
1041
|
+
}
|
|
1042
|
+
catch (errorArg) {
|
|
1043
|
+
// A partially initialized guard is deliberately fail-closed. It must
|
|
1044
|
+
// never be reclaimed automatically, or the guard would repeat the
|
|
1045
|
+
// fixed-path ownership race that it exists to prevent.
|
|
1046
|
+
throw errorArg;
|
|
1047
|
+
}
|
|
1048
|
+
return new UpgradeOwnershipMutationGuard(guardDirectory, owner);
|
|
1049
|
+
}
|
|
1050
|
+
catch (errorArg) {
|
|
1051
|
+
if (errorArg.code !== 'EEXIST')
|
|
1052
|
+
throw errorArg;
|
|
1053
|
+
}
|
|
1054
|
+
const stats = await lstatIfPresent(guardDirectory);
|
|
1055
|
+
if (!stats)
|
|
1056
|
+
continue;
|
|
1057
|
+
if (!stats.isDirectory()
|
|
1058
|
+
|| stats.isSymbolicLink()
|
|
1059
|
+
|| stats.uid !== this.uid
|
|
1060
|
+
|| (stats.mode & 0o077) !== 0)
|
|
1061
|
+
throw new Error(`Upgrade ownership mutation guard is unsafe: ${guardDirectory}`);
|
|
1062
|
+
let existingOwner;
|
|
1063
|
+
try {
|
|
1064
|
+
existingOwner = parseOwnershipMutationGuardOwner(await readPrivateJson(plugins.path.join(guardDirectory, ownerFileName)));
|
|
1065
|
+
}
|
|
1066
|
+
catch (errorArg) {
|
|
1067
|
+
const refreshedStats = await lstatIfPresent(guardDirectory);
|
|
1068
|
+
if (!refreshedStats || refreshedStats.dev !== stats.dev || refreshedStats.ino !== stats.ino) {
|
|
1069
|
+
continue;
|
|
1070
|
+
}
|
|
1071
|
+
if (Date.now() - refreshedStats.mtimeMs < initializationGraceMs
|
|
1072
|
+
&& Date.now() < deadline) {
|
|
1073
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
1076
|
+
throw new Error(`Upgrade ownership mutation guard is incomplete and cannot be reclaimed automatically: ${guardDirectory}. Inspect it after proving its owner is gone, or reboot the host to clear /tmp.`, { cause: errorArg });
|
|
1077
|
+
}
|
|
1078
|
+
if (existingOwner.uid !== this.uid || existingOwner.targetHash !== targetHash) {
|
|
1079
|
+
throw new Error(`Upgrade ownership mutation guard binding is invalid: ${guardDirectory}`);
|
|
1080
|
+
}
|
|
1081
|
+
let existingIdentity;
|
|
1082
|
+
try {
|
|
1083
|
+
existingIdentity = await readControllerProcessIdentity(existingOwner.pid);
|
|
1084
|
+
}
|
|
1085
|
+
catch (errorArg) {
|
|
1086
|
+
throw new Error(`The existing upgrade ownership mutation guard cannot be verified safely: ${guardDirectory}`, { cause: errorArg });
|
|
1087
|
+
}
|
|
1088
|
+
if (existingIdentity?.fingerprint !== existingOwner.fingerprint) {
|
|
1089
|
+
throw new Error(`Upgrade ownership mutation guard is stale and cannot be reclaimed automatically: ${guardDirectory}. Inspect it after proving its owner is gone, or reboot the host to clear /tmp.`);
|
|
1090
|
+
}
|
|
1091
|
+
if (Date.now() >= deadline) {
|
|
1092
|
+
throw new Error('Timed out waiting for an upgrade ownership mutation guard.');
|
|
1093
|
+
}
|
|
1094
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
async withOwnershipMutationGuard(directoryArg, operationArg) {
|
|
1098
|
+
const guard = await this.acquireOwnershipMutationGuard(directoryArg);
|
|
1099
|
+
let result;
|
|
1100
|
+
let operationError;
|
|
1101
|
+
try {
|
|
1102
|
+
result = await operationArg();
|
|
1103
|
+
}
|
|
1104
|
+
catch (errorArg) {
|
|
1105
|
+
operationError = errorArg;
|
|
1106
|
+
}
|
|
1107
|
+
let releaseError;
|
|
1108
|
+
try {
|
|
1109
|
+
await guard.release();
|
|
1110
|
+
}
|
|
1111
|
+
catch (errorArg) {
|
|
1112
|
+
releaseError = errorArg;
|
|
1113
|
+
}
|
|
1114
|
+
if (operationError !== undefined && releaseError !== undefined) {
|
|
1115
|
+
throw new AggregateError([operationError, releaseError], 'Upgrade ownership mutation failed and its guard could not be released.');
|
|
1116
|
+
}
|
|
1117
|
+
if (operationError !== undefined)
|
|
1118
|
+
throw operationError;
|
|
1119
|
+
if (releaseError !== undefined)
|
|
1120
|
+
throw releaseError;
|
|
1121
|
+
return result;
|
|
1122
|
+
}
|
|
1123
|
+
async reclaimStaleOwnedDirectory(directoryArg) {
|
|
1124
|
+
return await this.withOwnershipMutationGuard(directoryArg, async () => {
|
|
1125
|
+
const current = await this.inspectOwnedDirectory(directoryArg);
|
|
1126
|
+
if (current.state === 'absent')
|
|
1127
|
+
return false;
|
|
1128
|
+
if (current.state === 'indeterminate') {
|
|
1129
|
+
throw new Error(`The existing ${currentCliName} ownership cannot be verified safely.`);
|
|
1130
|
+
}
|
|
1131
|
+
if (current.state !== 'stale')
|
|
1132
|
+
return false;
|
|
1133
|
+
await removeExactOwnedDirectory(directoryArg, {
|
|
1134
|
+
identity: current.identity,
|
|
1135
|
+
...(current.owner
|
|
1136
|
+
? {
|
|
1137
|
+
assertOwner: (valueArg) => {
|
|
1138
|
+
const removedOwner = parseOwner(valueArg);
|
|
1139
|
+
if (!exactPrimitiveRecordMatches(removedOwner, current.owner)) {
|
|
1140
|
+
throw new Error('Upgrade coordination ownership changed during stale removal.');
|
|
1141
|
+
}
|
|
1142
|
+
},
|
|
1143
|
+
}
|
|
1144
|
+
: {}),
|
|
1145
|
+
});
|
|
1146
|
+
return true;
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
async releaseOwnedDirectory(directoryArg, expectedOwnerArg, shouldReleaseArg) {
|
|
1150
|
+
await this.withOwnershipMutationGuard(directoryArg, async () => {
|
|
1151
|
+
const stats = await plugins.fs.promises.lstat(directoryArg);
|
|
1152
|
+
let currentOwner;
|
|
1153
|
+
try {
|
|
1154
|
+
currentOwner = parseOwner(await readPrivateJson(plugins.path.join(directoryArg, ownerFileName)));
|
|
1155
|
+
}
|
|
1156
|
+
catch (errorArg) {
|
|
1157
|
+
if (errorArg.code === 'ENOENT') {
|
|
1158
|
+
throw new Error('Upgrade coordination ownership changed unexpectedly.', { cause: errorArg });
|
|
1159
|
+
}
|
|
1160
|
+
throw errorArg;
|
|
1161
|
+
}
|
|
1162
|
+
if (!exactPrimitiveRecordMatches(currentOwner, expectedOwnerArg)) {
|
|
1163
|
+
throw new Error('Upgrade coordination ownership changed unexpectedly.');
|
|
1164
|
+
}
|
|
1165
|
+
await removeExactOwnedDirectory(directoryArg, {
|
|
1166
|
+
identity: { dev: stats.dev, ino: stats.ino },
|
|
1167
|
+
...(shouldReleaseArg
|
|
1168
|
+
? {
|
|
1169
|
+
assertRemovalAuthorized: () => {
|
|
1170
|
+
if (!shouldReleaseArg()) {
|
|
1171
|
+
throw new Error('Upgrade coordination release is no longer authorized.');
|
|
1172
|
+
}
|
|
1173
|
+
},
|
|
1174
|
+
}
|
|
1175
|
+
: {}),
|
|
1176
|
+
assertOwner: (valueArg) => {
|
|
1177
|
+
const removedOwner = parseOwner(valueArg);
|
|
1178
|
+
if (!exactPrimitiveRecordMatches(removedOwner, expectedOwnerArg)) {
|
|
1179
|
+
throw new Error('Upgrade coordination ownership changed during release.');
|
|
1180
|
+
}
|
|
1181
|
+
},
|
|
1182
|
+
});
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
async inspectTransactionMutationDirectory(directoryArg, expectedTokenHashArg) {
|
|
1186
|
+
const stats = await lstatIfPresent(directoryArg);
|
|
1187
|
+
if (!stats)
|
|
1188
|
+
return { state: 'absent' };
|
|
1189
|
+
if (!stats.isDirectory()
|
|
1190
|
+
|| stats.isSymbolicLink()
|
|
1191
|
+
|| stats.uid !== this.uid
|
|
1192
|
+
|| (stats.mode & 0o077) !== 0)
|
|
1193
|
+
throw new Error('The upgrade transaction mutation lock is unsafe.');
|
|
1194
|
+
let rawOwner;
|
|
1195
|
+
try {
|
|
1196
|
+
rawOwner = await readPrivateJson(plugins.path.join(directoryArg, ownerFileName));
|
|
1197
|
+
}
|
|
1198
|
+
catch (errorArg) {
|
|
1199
|
+
const code = errorArg.code;
|
|
1200
|
+
if (code === 'HCON_INVALID_JSON') {
|
|
1201
|
+
return { state: 'indeterminate', identity: { dev: stats.dev, ino: stats.ino } };
|
|
1202
|
+
}
|
|
1203
|
+
if (code !== 'ENOENT')
|
|
1204
|
+
throw errorArg;
|
|
1205
|
+
return {
|
|
1206
|
+
state: Date.now() - stats.mtimeMs < initializationGraceMs
|
|
1207
|
+
? 'recent-invalid'
|
|
1208
|
+
: 'stale',
|
|
1209
|
+
identity: { dev: stats.dev, ino: stats.ino },
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
let owner;
|
|
1213
|
+
try {
|
|
1214
|
+
owner = parseTransactionMutationOwner(rawOwner);
|
|
1215
|
+
}
|
|
1216
|
+
catch {
|
|
1217
|
+
return { state: 'indeterminate', identity: { dev: stats.dev, ino: stats.ino } };
|
|
1218
|
+
}
|
|
1219
|
+
if (owner.uid !== this.uid
|
|
1220
|
+
|| (expectedTokenHashArg !== undefined
|
|
1221
|
+
&& !tokensEqual(owner.tokenHash, expectedTokenHashArg)))
|
|
1222
|
+
throw new Error('The upgrade transaction mutation lock binding is invalid.');
|
|
1223
|
+
try {
|
|
1224
|
+
const ownerIdentity = await readControllerProcessIdentity(owner.pid);
|
|
1225
|
+
return {
|
|
1226
|
+
state: ownerIdentity?.fingerprint === owner.fingerprint ? 'live' : 'stale',
|
|
1227
|
+
identity: { dev: stats.dev, ino: stats.ino },
|
|
1228
|
+
owner,
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
catch {
|
|
1232
|
+
return { state: 'indeterminate', identity: { dev: stats.dev, ino: stats.ino } };
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
async reclaimStaleTransactionMutationDirectory(directoryArg, expectedTokenHashArg) {
|
|
1236
|
+
return await this.withOwnershipMutationGuard(directoryArg, async () => {
|
|
1237
|
+
const current = await this.inspectTransactionMutationDirectory(directoryArg, expectedTokenHashArg);
|
|
1238
|
+
if (current.state === 'absent')
|
|
1239
|
+
return false;
|
|
1240
|
+
if (current.state === 'indeterminate') {
|
|
1241
|
+
throw new Error('The upgrade transaction mutation owner cannot be verified safely.');
|
|
1242
|
+
}
|
|
1243
|
+
if (current.state !== 'stale')
|
|
1244
|
+
return false;
|
|
1245
|
+
await removeExactOwnedDirectory(directoryArg, {
|
|
1246
|
+
identity: current.identity,
|
|
1247
|
+
...(current.owner
|
|
1248
|
+
? {
|
|
1249
|
+
assertOwner: (valueArg) => {
|
|
1250
|
+
const removedOwner = parseTransactionMutationOwner(valueArg);
|
|
1251
|
+
if (!exactPrimitiveRecordMatches(removedOwner, current.owner)) {
|
|
1252
|
+
throw new Error('The upgrade transaction mutation owner changed during stale removal.');
|
|
1253
|
+
}
|
|
1254
|
+
},
|
|
1255
|
+
}
|
|
1256
|
+
: {}),
|
|
1257
|
+
});
|
|
1258
|
+
return true;
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
async inspectOwnedDirectory(directoryArg) {
|
|
1262
|
+
let stats;
|
|
1263
|
+
try {
|
|
1264
|
+
stats = await plugins.fs.promises.lstat(directoryArg);
|
|
1265
|
+
}
|
|
1266
|
+
catch (errorArg) {
|
|
1267
|
+
if (errorArg.code === 'ENOENT')
|
|
1268
|
+
return { state: 'absent' };
|
|
1269
|
+
throw errorArg;
|
|
1270
|
+
}
|
|
1271
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
1272
|
+
throw new Error(`Upgrade coordination owner path is unsafe: ${directoryArg}`);
|
|
1273
|
+
}
|
|
1274
|
+
if (stats.uid !== this.uid || (stats.mode & 0o077) !== 0) {
|
|
1275
|
+
throw new Error(`Upgrade coordination owner path is not private: ${directoryArg}`);
|
|
1276
|
+
}
|
|
1277
|
+
let ownerValue;
|
|
1278
|
+
try {
|
|
1279
|
+
ownerValue = await readPrivateJson(plugins.path.join(directoryArg, ownerFileName));
|
|
1280
|
+
}
|
|
1281
|
+
catch (errorArg) {
|
|
1282
|
+
const code = errorArg.code;
|
|
1283
|
+
if (code === 'HCON_INVALID_JSON') {
|
|
1284
|
+
return { state: 'indeterminate', identity: { dev: stats.dev, ino: stats.ino } };
|
|
1285
|
+
}
|
|
1286
|
+
if (code !== 'ENOENT')
|
|
1287
|
+
throw errorArg;
|
|
1288
|
+
return {
|
|
1289
|
+
state: Date.now() - stats.mtimeMs < initializationGraceMs
|
|
1290
|
+
? 'recent-invalid'
|
|
1291
|
+
: 'stale',
|
|
1292
|
+
identity: { dev: stats.dev, ino: stats.ino },
|
|
1293
|
+
};
|
|
1294
|
+
}
|
|
1295
|
+
let owner;
|
|
1296
|
+
try {
|
|
1297
|
+
owner = parseOwner(ownerValue);
|
|
1298
|
+
}
|
|
1299
|
+
catch {
|
|
1300
|
+
return { state: 'indeterminate', identity: { dev: stats.dev, ino: stats.ino } };
|
|
1301
|
+
}
|
|
1302
|
+
try {
|
|
1303
|
+
return {
|
|
1304
|
+
state: await ownerIsLive(owner) ? 'live' : 'stale',
|
|
1305
|
+
identity: { dev: stats.dev, ino: stats.ino },
|
|
1306
|
+
owner,
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
catch {
|
|
1310
|
+
return { state: 'indeterminate', identity: { dev: stats.dev, ino: stats.ino } };
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
async createOwnedDirectory(directoryArg, ownerArg) {
|
|
1314
|
+
return await this.withOwnershipMutationGuard(directoryArg, async () => {
|
|
1315
|
+
try {
|
|
1316
|
+
await plugins.fs.promises.mkdir(directoryArg, { mode: 0o700 });
|
|
1317
|
+
}
|
|
1318
|
+
catch (errorArg) {
|
|
1319
|
+
if (errorArg.code === 'EEXIST')
|
|
1320
|
+
return undefined;
|
|
1321
|
+
throw errorArg;
|
|
1322
|
+
}
|
|
1323
|
+
try {
|
|
1324
|
+
await writePrivateJson(plugins.path.join(directoryArg, ownerFileName), ownerArg);
|
|
1325
|
+
await syncDirectory(plugins.path.dirname(directoryArg));
|
|
1326
|
+
return { directory: directoryArg, owner: ownerArg };
|
|
1327
|
+
}
|
|
1328
|
+
catch (errorArg) {
|
|
1329
|
+
// Preserve a failed initialization directory. Contenders treat it as
|
|
1330
|
+
// recent-invalid, then reclaim it only after the bounded grace period.
|
|
1331
|
+
throw errorArg;
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
async acquireUpgradeLock(optionsArg) {
|
|
1336
|
+
await this.init();
|
|
1337
|
+
const owner = await ownerForCurrentProcess('upgrade', optionsArg.token, optionsArg.cliPath, optionsArg.command ?? '__upgrade-worker');
|
|
1338
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
1339
|
+
const created = await this.createOwnedDirectory(this.upgradeLockDirectory, owner);
|
|
1340
|
+
if (created)
|
|
1341
|
+
return new UpgradeInstallationLock(created.directory, created.owner, (directoryArg, ownerArg, shouldReleaseArg) => this.releaseOwnedDirectory(directoryArg, ownerArg, shouldReleaseArg));
|
|
1342
|
+
const state = await this.inspectOwnedDirectory(this.upgradeLockDirectory);
|
|
1343
|
+
if (state.state === 'live') {
|
|
1344
|
+
let currentOwner;
|
|
1345
|
+
try {
|
|
1346
|
+
currentOwner = parseOwner(await readPrivateJson(plugins.path.join(this.upgradeLockDirectory, ownerFileName)));
|
|
1347
|
+
}
|
|
1348
|
+
catch (errorArg) {
|
|
1349
|
+
if (errorArg.code === 'ENOENT')
|
|
1350
|
+
continue;
|
|
1351
|
+
throw errorArg;
|
|
1352
|
+
}
|
|
1353
|
+
if (currentOwner.pid === owner.pid
|
|
1354
|
+
&& currentOwner.fingerprint === owner.fingerprint
|
|
1355
|
+
&& tokensEqual(currentOwner.tokenHash, owner.tokenHash))
|
|
1356
|
+
return new UpgradeInstallationLock(this.upgradeLockDirectory, currentOwner, (directoryArg, ownerArg, shouldReleaseArg) => this.releaseOwnedDirectory(directoryArg, ownerArg, shouldReleaseArg));
|
|
1357
|
+
throw new Error(`Another ${currentCliName} upgrade is already running.`);
|
|
1358
|
+
}
|
|
1359
|
+
if (state.state === 'recent-invalid') {
|
|
1360
|
+
throw new Error(`Another ${currentCliName} upgrade is initializing; retry shortly.`);
|
|
1361
|
+
}
|
|
1362
|
+
if (state.state === 'stale') {
|
|
1363
|
+
await this.reclaimStaleOwnedDirectory(this.upgradeLockDirectory);
|
|
1364
|
+
}
|
|
1365
|
+
if (state.state === 'indeterminate') {
|
|
1366
|
+
throw new Error(`The existing ${currentCliName} upgrade owner cannot be verified safely.`);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
throw new Error(`Unable to acquire exclusive ${currentCliName} upgrade ownership.`);
|
|
1370
|
+
}
|
|
1371
|
+
async transferUpgradeLockToWorker(optionsArg) {
|
|
1372
|
+
const identity = await readControllerProcessIdentity(optionsArg.worker.pid);
|
|
1373
|
+
if (!identity
|
|
1374
|
+
|| identity.fingerprint !== optionsArg.worker.fingerprint
|
|
1375
|
+
|| identity.processGroupId !== optionsArg.worker.processGroupId
|
|
1376
|
+
|| !identity.processGroupLeader
|
|
1377
|
+
|| !await processIdentityHasCliCommand(identity, optionsArg.worker.cliPath, '__upgrade-worker', { allowMissingAbsolutePath: true }))
|
|
1378
|
+
throw new Error('The upgrade lock transfer worker identity is invalid.');
|
|
1379
|
+
const owner = {
|
|
1380
|
+
version: coordinationVersion,
|
|
1381
|
+
kind: 'upgrade',
|
|
1382
|
+
uid: this.uid,
|
|
1383
|
+
tokenHash: hashToken(optionsArg.token),
|
|
1384
|
+
pid: identity.pid,
|
|
1385
|
+
processGroupId: identity.processGroupId,
|
|
1386
|
+
fingerprint: identity.fingerprint,
|
|
1387
|
+
cliPath: optionsArg.worker.cliPath,
|
|
1388
|
+
command: '__upgrade-worker',
|
|
1389
|
+
createdAt: Date.now(),
|
|
1390
|
+
};
|
|
1391
|
+
await this.withOwnershipMutationGuard(this.upgradeLockDirectory, async () => {
|
|
1392
|
+
await optionsArg.lock.assertOwned();
|
|
1393
|
+
const ownerPath = plugins.path.join(this.upgradeLockDirectory, ownerFileName);
|
|
1394
|
+
const temporaryPath = `${ownerPath}.transfer-${process.pid}-${plugins.crypto.randomBytes(4).toString('hex')}`;
|
|
1395
|
+
try {
|
|
1396
|
+
await writePrivateJson(temporaryPath, owner);
|
|
1397
|
+
await plugins.fs.promises.rename(temporaryPath, ownerPath);
|
|
1398
|
+
await syncDirectory(this.upgradeLockDirectory);
|
|
1399
|
+
optionsArg.lock.relinquishAfterTransfer();
|
|
1400
|
+
}
|
|
1401
|
+
finally {
|
|
1402
|
+
await plugins.fs.promises.unlink(temporaryPath).catch(() => undefined);
|
|
1403
|
+
}
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
async readLiveUpgradeOwner() {
|
|
1407
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
1408
|
+
const state = await this.inspectOwnedDirectory(this.upgradeLockDirectory);
|
|
1409
|
+
if (state.state === 'absent')
|
|
1410
|
+
return undefined;
|
|
1411
|
+
if (state.state === 'recent-invalid') {
|
|
1412
|
+
throw new Error(`An ${currentCliName} upgrade is initializing; retry shortly.`);
|
|
1413
|
+
}
|
|
1414
|
+
if (state.state === 'indeterminate') {
|
|
1415
|
+
throw new Error(`The existing ${currentCliName} upgrade owner cannot be verified safely.`);
|
|
1416
|
+
}
|
|
1417
|
+
if (state.state === 'stale') {
|
|
1418
|
+
await this.reclaimStaleOwnedDirectory(this.upgradeLockDirectory);
|
|
1419
|
+
continue;
|
|
1420
|
+
}
|
|
1421
|
+
try {
|
|
1422
|
+
return parseOwner(await readPrivateJson(plugins.path.join(this.upgradeLockDirectory, ownerFileName)));
|
|
1423
|
+
}
|
|
1424
|
+
catch (errorArg) {
|
|
1425
|
+
if (errorArg.code !== 'ENOENT')
|
|
1426
|
+
throw errorArg;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
throw new Error(`The ${currentCliName} upgrade owner changed repeatedly during admission.`);
|
|
1430
|
+
}
|
|
1431
|
+
async acquireStartLease(optionsArg) {
|
|
1432
|
+
await this.init();
|
|
1433
|
+
const owner = await ownerForCurrentProcess('start', optionsArg.token, optionsArg.cliPath, optionsArg.command);
|
|
1434
|
+
const upgradeOwnerBefore = await this.readLiveUpgradeOwner();
|
|
1435
|
+
const authorized = upgradeOwnerBefore !== undefined
|
|
1436
|
+
&& optionsArg.upgradeToken !== undefined
|
|
1437
|
+
&& tokensEqual(upgradeOwnerBefore.tokenHash, hashToken(optionsArg.upgradeToken));
|
|
1438
|
+
if (upgradeOwnerBefore && !authorized) {
|
|
1439
|
+
throw new Error(`${currentCliName} cannot start while a global upgrade is in progress.`);
|
|
1440
|
+
}
|
|
1441
|
+
const leaseDirectory = plugins.path.join(this.startLeasesDirectory, coordinationPathHash(assertToken(optionsArg.token)));
|
|
1442
|
+
const created = await this.createOwnedDirectory(leaseDirectory, owner);
|
|
1443
|
+
if (!created)
|
|
1444
|
+
throw new Error(`The ${currentCliName} start admission token is already in use.`);
|
|
1445
|
+
const lease = new UpgradeStartLease(created.directory, created.owner, (directoryArg, ownerArg, shouldReleaseArg) => this.releaseOwnedDirectory(directoryArg, ownerArg, shouldReleaseArg));
|
|
1446
|
+
try {
|
|
1447
|
+
const upgradeOwnerAfter = await this.readLiveUpgradeOwner();
|
|
1448
|
+
if (upgradeOwnerAfter) {
|
|
1449
|
+
const remainsAuthorized = optionsArg.upgradeToken !== undefined
|
|
1450
|
+
&& tokensEqual(upgradeOwnerAfter.tokenHash, hashToken(optionsArg.upgradeToken));
|
|
1451
|
+
if (!remainsAuthorized) {
|
|
1452
|
+
throw new Error(`${currentCliName} upgrade began while startup was entering admission.`);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
return lease;
|
|
1456
|
+
}
|
|
1457
|
+
catch (errorArg) {
|
|
1458
|
+
await lease.release();
|
|
1459
|
+
throw errorArg;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
async waitForStartLeasesToDrain(lockArg) {
|
|
1463
|
+
const deadline = Date.now() + startLeaseDrainTimeoutMs;
|
|
1464
|
+
while (Date.now() < deadline) {
|
|
1465
|
+
await lockArg.assertOwned();
|
|
1466
|
+
const entries = await plugins.fs.promises.readdir(this.startLeasesDirectory, {
|
|
1467
|
+
withFileTypes: true,
|
|
1468
|
+
});
|
|
1469
|
+
let blocked = false;
|
|
1470
|
+
for (const entry of entries) {
|
|
1471
|
+
if (!entry.isDirectory() || !leaseDirectoryPattern.test(entry.name)) {
|
|
1472
|
+
throw new Error(`The ${currentCliName} start admission directory contains an unexpected entry.`);
|
|
1473
|
+
}
|
|
1474
|
+
const leaseDirectory = plugins.path.join(this.startLeasesDirectory, entry.name);
|
|
1475
|
+
const state = await this.inspectOwnedDirectory(leaseDirectory);
|
|
1476
|
+
if (state.state === 'live' || state.state === 'recent-invalid') {
|
|
1477
|
+
blocked = true;
|
|
1478
|
+
continue;
|
|
1479
|
+
}
|
|
1480
|
+
if (state.state === 'indeterminate') {
|
|
1481
|
+
throw new Error(`An ${currentCliName} start admission owner cannot be verified safely.`);
|
|
1482
|
+
}
|
|
1483
|
+
if (state.state === 'stale') {
|
|
1484
|
+
if (!await this.reclaimStaleOwnedDirectory(leaseDirectory))
|
|
1485
|
+
blocked = true;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
if (!blocked)
|
|
1489
|
+
return;
|
|
1490
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1491
|
+
}
|
|
1492
|
+
throw new Error(`Timed out waiting for an in-flight ${currentCliName} start to finish.`);
|
|
1493
|
+
}
|
|
1494
|
+
tokenFilePath(kindArg, tokenArg) {
|
|
1495
|
+
return plugins.path.join(this.baseDirectory, `${kindArg}-${coordinationPathHash(assertToken(tokenArg))}.json`);
|
|
1496
|
+
}
|
|
1497
|
+
transactionFilePath(tokenArg) {
|
|
1498
|
+
return plugins.path.join(this.transactionsDirectory, `transaction-${coordinationPathHash(assertToken(tokenArg))}.json`);
|
|
1499
|
+
}
|
|
1500
|
+
transactionMutationDirectory(tokenArg) {
|
|
1501
|
+
return `${this.transactionFilePath(tokenArg)}.lock`;
|
|
1502
|
+
}
|
|
1503
|
+
async withTransactionMutation(tokenArg, operationArg) {
|
|
1504
|
+
await this.init();
|
|
1505
|
+
const lockDirectory = this.transactionMutationDirectory(tokenArg);
|
|
1506
|
+
const deadline = Date.now() + transactionMutationTimeoutMs;
|
|
1507
|
+
const identity = await readControllerProcessIdentity(process.pid);
|
|
1508
|
+
if (!identity)
|
|
1509
|
+
throw new Error('Unable to establish transaction mutation ownership.');
|
|
1510
|
+
const owner = {
|
|
1511
|
+
version: coordinationVersion,
|
|
1512
|
+
uid: this.uid,
|
|
1513
|
+
tokenHash: hashToken(tokenArg),
|
|
1514
|
+
pid: identity.pid,
|
|
1515
|
+
fingerprint: identity.fingerprint,
|
|
1516
|
+
nonce: plugins.crypto.randomBytes(16).toString('hex'),
|
|
1517
|
+
createdAt: Date.now(),
|
|
1518
|
+
};
|
|
1519
|
+
while (true) {
|
|
1520
|
+
try {
|
|
1521
|
+
await plugins.fs.promises.mkdir(lockDirectory, { mode: 0o700 });
|
|
1522
|
+
try {
|
|
1523
|
+
await writePrivateJson(plugins.path.join(lockDirectory, ownerFileName), owner);
|
|
1524
|
+
}
|
|
1525
|
+
catch (errorArg) {
|
|
1526
|
+
// Leave partial initialization for the next contender's bounded stale check.
|
|
1527
|
+
throw errorArg;
|
|
1528
|
+
}
|
|
1529
|
+
break;
|
|
1530
|
+
}
|
|
1531
|
+
catch (errorArg) {
|
|
1532
|
+
if (errorArg.code !== 'EEXIST')
|
|
1533
|
+
throw errorArg;
|
|
1534
|
+
const current = await this.inspectTransactionMutationDirectory(lockDirectory, owner.tokenHash);
|
|
1535
|
+
if (current.state === 'absent')
|
|
1536
|
+
continue;
|
|
1537
|
+
if (current.state === 'stale') {
|
|
1538
|
+
await this.reclaimStaleTransactionMutationDirectory(lockDirectory, owner.tokenHash);
|
|
1539
|
+
continue;
|
|
1540
|
+
}
|
|
1541
|
+
if (current.state === 'indeterminate') {
|
|
1542
|
+
throw new Error('The upgrade transaction mutation owner cannot be verified safely.');
|
|
1543
|
+
}
|
|
1544
|
+
if (Date.now() >= deadline) {
|
|
1545
|
+
throw new Error('Timed out waiting to update the upgrade transaction.');
|
|
1546
|
+
}
|
|
1547
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
let result;
|
|
1551
|
+
let operationError;
|
|
1552
|
+
try {
|
|
1553
|
+
result = await operationArg();
|
|
1554
|
+
}
|
|
1555
|
+
catch (errorArg) {
|
|
1556
|
+
operationError = errorArg;
|
|
1557
|
+
}
|
|
1558
|
+
let releaseError;
|
|
1559
|
+
try {
|
|
1560
|
+
await this.withOwnershipMutationGuard(lockDirectory, async () => {
|
|
1561
|
+
const stats = await plugins.fs.promises.lstat(lockDirectory);
|
|
1562
|
+
let currentOwner;
|
|
1563
|
+
try {
|
|
1564
|
+
currentOwner = parseTransactionMutationOwner(await readPrivateJson(plugins.path.join(lockDirectory, ownerFileName)));
|
|
1565
|
+
}
|
|
1566
|
+
catch (errorArg) {
|
|
1567
|
+
if (errorArg.code === 'ENOENT') {
|
|
1568
|
+
throw new Error('The upgrade transaction mutation lock ownership changed unexpectedly.', { cause: errorArg });
|
|
1569
|
+
}
|
|
1570
|
+
throw errorArg;
|
|
1571
|
+
}
|
|
1572
|
+
if (!exactPrimitiveRecordMatches(currentOwner, owner)) {
|
|
1573
|
+
throw new Error('The upgrade transaction mutation lock ownership changed unexpectedly.');
|
|
1574
|
+
}
|
|
1575
|
+
await removeExactOwnedDirectory(lockDirectory, {
|
|
1576
|
+
identity: { dev: stats.dev, ino: stats.ino },
|
|
1577
|
+
assertOwner: (valueArg) => {
|
|
1578
|
+
const removedOwner = parseTransactionMutationOwner(valueArg);
|
|
1579
|
+
if (!exactPrimitiveRecordMatches(removedOwner, owner)) {
|
|
1580
|
+
throw new Error('The upgrade transaction mutation lock ownership changed during release.');
|
|
1581
|
+
}
|
|
1582
|
+
},
|
|
1583
|
+
});
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
catch (errorArg) {
|
|
1587
|
+
releaseError = errorArg;
|
|
1588
|
+
}
|
|
1589
|
+
if (operationError !== undefined && releaseError !== undefined) {
|
|
1590
|
+
throw new AggregateError([operationError, releaseError], 'The upgrade transaction mutation failed and its ownership could not be released.');
|
|
1591
|
+
}
|
|
1592
|
+
if (operationError !== undefined)
|
|
1593
|
+
throw operationError;
|
|
1594
|
+
if (releaseError !== undefined)
|
|
1595
|
+
throw releaseError;
|
|
1596
|
+
return result;
|
|
1597
|
+
}
|
|
1598
|
+
async createTransaction(optionsArg) {
|
|
1599
|
+
await this.init();
|
|
1600
|
+
const now = Date.now();
|
|
1601
|
+
const transaction = {
|
|
1602
|
+
version: coordinationVersion,
|
|
1603
|
+
tokenHash: hashToken(optionsArg.token),
|
|
1604
|
+
revision: 0,
|
|
1605
|
+
port: assertPort(optionsArg.port),
|
|
1606
|
+
sourceVersion: assertBoundedText(optionsArg.sourceVersion, 'The upgrade source version', 128),
|
|
1607
|
+
controllerWasRunning: optionsArg.controllerWasRunning,
|
|
1608
|
+
continueSessions: optionsArg.continueSessions,
|
|
1609
|
+
gracePeriodMs: optionsArg.gracePeriodMs,
|
|
1610
|
+
phase: 'starting',
|
|
1611
|
+
message: 'Upgrade worker is starting.',
|
|
1612
|
+
createdAt: now,
|
|
1613
|
+
phaseStartedAt: now,
|
|
1614
|
+
updatedAt: now,
|
|
1615
|
+
sessions: [],
|
|
1616
|
+
};
|
|
1617
|
+
const validated = parseUpgradeTransactionV2(transaction);
|
|
1618
|
+
await writePrivateJson(this.transactionFilePath(optionsArg.token), validated);
|
|
1619
|
+
return validated;
|
|
1620
|
+
}
|
|
1621
|
+
async createPackageTransitionTransaction(optionsArg) {
|
|
1622
|
+
await this.init();
|
|
1623
|
+
const now = Date.now();
|
|
1624
|
+
const transaction = {
|
|
1625
|
+
version: upgradePackageTransitionTransactionVersion,
|
|
1626
|
+
tokenHash: hashToken(optionsArg.token),
|
|
1627
|
+
revision: 0,
|
|
1628
|
+
port: assertPort(optionsArg.port),
|
|
1629
|
+
sourcePackageName: upgradePackageTransitionSource.packageName,
|
|
1630
|
+
sourceVersion: upgradePackageTransitionSource.version,
|
|
1631
|
+
sourceManagementVersion: upgradePackageTransitionSource.managementVersion,
|
|
1632
|
+
sourceCliName: upgradePackageTransitionSource.cliName,
|
|
1633
|
+
sourceCliRelativePath: upgradePackageTransitionSource.cliRelativePath,
|
|
1634
|
+
targetPackageName: upgradePackageTransitionTarget.packageName,
|
|
1635
|
+
targetVersion: upgradePackageTransitionTarget.version,
|
|
1636
|
+
targetManagementVersion: upgradePackageTransitionTarget.managementVersion,
|
|
1637
|
+
targetCliName: upgradePackageTransitionTarget.cliName,
|
|
1638
|
+
targetCliRelativePath: upgradePackageTransitionTarget.cliRelativePath,
|
|
1639
|
+
controllerWasRunning: optionsArg.controllerWasRunning,
|
|
1640
|
+
continueSessions: optionsArg.continueSessions,
|
|
1641
|
+
gracePeriodMs: optionsArg.gracePeriodMs,
|
|
1642
|
+
phase: 'starting',
|
|
1643
|
+
message: 'Upgrade worker is starting.',
|
|
1644
|
+
createdAt: now,
|
|
1645
|
+
phaseStartedAt: now,
|
|
1646
|
+
updatedAt: now,
|
|
1647
|
+
sessions: [],
|
|
1648
|
+
};
|
|
1649
|
+
const validated = parseUpgradeTransactionV3(transaction);
|
|
1650
|
+
await writePrivateJson(this.transactionFilePath(optionsArg.token), validated);
|
|
1651
|
+
return validated;
|
|
1652
|
+
}
|
|
1653
|
+
async readTransaction(tokenArg) {
|
|
1654
|
+
await this.init();
|
|
1655
|
+
const transaction = parseUpgradeTransaction(await readPrivateJson(this.transactionFilePath(tokenArg)));
|
|
1656
|
+
if (!tokensEqual(transaction.tokenHash, hashToken(tokenArg))) {
|
|
1657
|
+
throw new Error('The upgrade transaction token binding is invalid.');
|
|
1658
|
+
}
|
|
1659
|
+
return transaction;
|
|
1660
|
+
}
|
|
1661
|
+
async updateTransaction(tokenArg, expectedRevisionArg, updateArg) {
|
|
1662
|
+
return await this.withTransactionMutation(tokenArg, async () => {
|
|
1663
|
+
const current = await this.readTransaction(tokenArg);
|
|
1664
|
+
if (current.revision !== expectedRevisionArg) {
|
|
1665
|
+
throw new Error('The upgrade transaction changed concurrently.');
|
|
1666
|
+
}
|
|
1667
|
+
return await this.writeTransactionUpdate(tokenArg, current, updateArg(current));
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1670
|
+
async mutateTransaction(tokenArg, updateArg) {
|
|
1671
|
+
return await this.withTransactionMutation(tokenArg, async () => {
|
|
1672
|
+
const current = await this.readTransaction(tokenArg);
|
|
1673
|
+
return await this.writeTransactionUpdate(tokenArg, current, updateArg(current));
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
async writeTransactionUpdate(tokenArg, currentArg, updatedArg) {
|
|
1677
|
+
const updatedAt = Date.now();
|
|
1678
|
+
const workerIdentityChanged = (currentArg.worker?.pid !== updatedArg.worker?.pid
|
|
1679
|
+
|| currentArg.worker?.processGroupId !== updatedArg.worker?.processGroupId
|
|
1680
|
+
|| currentArg.worker?.fingerprint !== updatedArg.worker?.fingerprint
|
|
1681
|
+
|| currentArg.worker?.cliPath !== updatedArg.worker?.cliPath);
|
|
1682
|
+
const next = parseUpgradeTransaction({
|
|
1683
|
+
...updatedArg,
|
|
1684
|
+
version: currentArg.version,
|
|
1685
|
+
tokenHash: currentArg.tokenHash,
|
|
1686
|
+
revision: currentArg.revision + 1,
|
|
1687
|
+
createdAt: currentArg.createdAt,
|
|
1688
|
+
phaseStartedAt: updatedArg.phase === currentArg.phase && !workerIdentityChanged
|
|
1689
|
+
? currentArg.phaseStartedAt
|
|
1690
|
+
: updatedAt,
|
|
1691
|
+
updatedAt,
|
|
1692
|
+
});
|
|
1693
|
+
if (transactionPhaseOrder[next.phase] < transactionPhaseOrder[currentArg.phase]) {
|
|
1694
|
+
throw new Error('The upgrade transaction phase cannot regress.');
|
|
1695
|
+
}
|
|
1696
|
+
if (currentArg.version === upgradePackageTransitionTransactionVersion) {
|
|
1697
|
+
if (next.version !== upgradePackageTransitionTransactionVersion) {
|
|
1698
|
+
throw new Error('The upgrade transaction version cannot change.');
|
|
1699
|
+
}
|
|
1700
|
+
for (const checkpoint of [
|
|
1701
|
+
'packageTransitionStarted',
|
|
1702
|
+
'groupedTargetVerified',
|
|
1703
|
+
'targetPackageCommitStarted',
|
|
1704
|
+
'targetPackageCommitted',
|
|
1705
|
+
'targetStartupInvoked',
|
|
1706
|
+
]) {
|
|
1707
|
+
if (currentArg[checkpoint] === true && next[checkpoint] !== true) {
|
|
1708
|
+
throw new Error(`The upgrade package-transition checkpoint ${checkpoint} cannot regress.`);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
if ((currentArg.preparationAcceptedAt !== undefined
|
|
1713
|
+
&& next.preparationAcceptedAt !== currentArg.preparationAcceptedAt)
|
|
1714
|
+
|| (currentArg.preparationDeadlineAt !== undefined
|
|
1715
|
+
&& next.preparationDeadlineAt !== currentArg.preparationDeadlineAt)
|
|
1716
|
+
|| (currentArg.preparationCompletedAt !== undefined
|
|
1717
|
+
&& next.preparationCompletedAt !== currentArg.preparationCompletedAt)
|
|
1718
|
+
|| (currentArg.preparationAcceptedAt === undefined
|
|
1719
|
+
&& currentArg.preparationDeadlineAt === undefined
|
|
1720
|
+
&& next.preparationCompletedAt !== undefined))
|
|
1721
|
+
throw new Error('The upgrade preparation timeline cannot change after it is committed.');
|
|
1722
|
+
const targetPath = this.transactionFilePath(tokenArg);
|
|
1723
|
+
const temporaryPath = `${targetPath}.tmp-${process.pid}-${plugins.crypto.randomBytes(4).toString('hex')}`;
|
|
1724
|
+
try {
|
|
1725
|
+
await writePrivateJson(temporaryPath, next);
|
|
1726
|
+
await plugins.fs.promises.rename(temporaryPath, targetPath);
|
|
1727
|
+
await syncDirectory(this.transactionsDirectory);
|
|
1728
|
+
}
|
|
1729
|
+
finally {
|
|
1730
|
+
await plugins.fs.promises.unlink(temporaryPath).catch(() => undefined);
|
|
1731
|
+
}
|
|
1732
|
+
return next;
|
|
1733
|
+
}
|
|
1734
|
+
async registerWorker(tokenArg, cliPathArg) {
|
|
1735
|
+
const identity = await readControllerProcessIdentity(process.pid);
|
|
1736
|
+
if (!identity)
|
|
1737
|
+
throw new Error('Unable to establish upgrade worker ownership.');
|
|
1738
|
+
return await this.mutateTransaction(tokenArg, (current) => ({
|
|
1739
|
+
...current,
|
|
1740
|
+
worker: {
|
|
1741
|
+
pid: identity.pid,
|
|
1742
|
+
processGroupId: identity.processGroupId,
|
|
1743
|
+
fingerprint: identity.fingerprint,
|
|
1744
|
+
cliPath: cliPathArg,
|
|
1745
|
+
...(current.worker?.logFilePath ? { logFilePath: current.worker.logFilePath } : {}),
|
|
1746
|
+
},
|
|
1747
|
+
phase: 'checking',
|
|
1748
|
+
message: 'Checking the npm latest version.',
|
|
1749
|
+
}));
|
|
1750
|
+
}
|
|
1751
|
+
async recordWorkerLaunch(tokenArg, pidArg, cliPathArg, logFilePathArg) {
|
|
1752
|
+
const identity = await readControllerProcessIdentity(pidArg);
|
|
1753
|
+
if (!identity
|
|
1754
|
+
|| !identity.processGroupLeader
|
|
1755
|
+
|| !await processIdentityHasCliCommand(identity, cliPathArg, '__upgrade-worker', { allowMissingAbsolutePath: true }))
|
|
1756
|
+
throw new Error('Unable to verify the launched upgrade worker identity.');
|
|
1757
|
+
const logFilePath = assertBoundedText(logFilePathArg, 'The upgrade worker log path', 4_096);
|
|
1758
|
+
if (!plugins.path.isAbsolute(logFilePath)) {
|
|
1759
|
+
throw new Error('The upgrade worker log path must be absolute.');
|
|
1760
|
+
}
|
|
1761
|
+
return await this.mutateTransaction(tokenArg, (current) => ({
|
|
1762
|
+
...current,
|
|
1763
|
+
worker: {
|
|
1764
|
+
pid: identity.pid,
|
|
1765
|
+
processGroupId: identity.processGroupId,
|
|
1766
|
+
fingerprint: identity.fingerprint,
|
|
1767
|
+
cliPath: cliPathArg,
|
|
1768
|
+
logFilePath,
|
|
1769
|
+
},
|
|
1770
|
+
}));
|
|
1771
|
+
}
|
|
1772
|
+
async recordController(tokenArg, controllerArg) {
|
|
1773
|
+
if (!controllerArg)
|
|
1774
|
+
throw new Error('The upgrade controller identity is required.');
|
|
1775
|
+
const identity = await readControllerProcessIdentity(controllerArg.pid);
|
|
1776
|
+
if (!identity
|
|
1777
|
+
|| identity.fingerprint !== controllerArg.fingerprint
|
|
1778
|
+
|| identity.processGroupId !== controllerArg.processGroupId
|
|
1779
|
+
|| !await processIdentityHasCliCommand(identity, controllerArg.cliPath, controllerArg.command, { allowMissingAbsolutePath: true }))
|
|
1780
|
+
throw new Error('Unable to verify the upgrade controller identity.');
|
|
1781
|
+
return await this.mutateTransaction(tokenArg, (current) => ({
|
|
1782
|
+
...current,
|
|
1783
|
+
controller: { ...controllerArg },
|
|
1784
|
+
}));
|
|
1785
|
+
}
|
|
1786
|
+
async transactionControllerIsLive(transactionArg) {
|
|
1787
|
+
const controller = transactionArg.controller;
|
|
1788
|
+
if (!controller)
|
|
1789
|
+
return false;
|
|
1790
|
+
const identity = await readControllerProcessIdentity(controller.pid);
|
|
1791
|
+
return Boolean(identity?.fingerprint === controller.fingerprint
|
|
1792
|
+
&& identity.processGroupId === controller.processGroupId
|
|
1793
|
+
&& await processIdentityHasCliCommand(identity, controller.cliPath, controller.command, { allowMissingAbsolutePath: true }));
|
|
1794
|
+
}
|
|
1795
|
+
async transactionWorkerIsLive(transactionArg) {
|
|
1796
|
+
const worker = transactionArg.worker;
|
|
1797
|
+
if (!worker)
|
|
1798
|
+
return false;
|
|
1799
|
+
const identity = await readControllerProcessIdentity(worker.pid);
|
|
1800
|
+
if (Boolean(identity?.fingerprint === worker.fingerprint
|
|
1801
|
+
&& await processIdentityHasCliCommand(identity, worker.cliPath, '__upgrade-worker', { allowMissingAbsolutePath: true })))
|
|
1802
|
+
return true;
|
|
1803
|
+
if (worker.processGroupId !== worker.pid)
|
|
1804
|
+
return false;
|
|
1805
|
+
return (await readProcessGroupMemberPids(worker.processGroupId))
|
|
1806
|
+
.some((processIdArg) => processIdArg !== worker.pid);
|
|
1807
|
+
}
|
|
1808
|
+
async terminateTransactionWorker(transactionArg) {
|
|
1809
|
+
const worker = transactionArg.worker;
|
|
1810
|
+
if (!worker)
|
|
1811
|
+
return;
|
|
1812
|
+
await this.terminateUpgradeWorkerCandidate(worker);
|
|
1813
|
+
}
|
|
1814
|
+
async terminateUpgradeWorkerCandidate(worker) {
|
|
1815
|
+
const identity = await readControllerProcessIdentity(worker.pid);
|
|
1816
|
+
if (identity) {
|
|
1817
|
+
if (identity.fingerprint !== worker.fingerprint
|
|
1818
|
+
|| identity.processGroupId !== worker.processGroupId
|
|
1819
|
+
|| !identity.processGroupLeader
|
|
1820
|
+
|| !await processIdentityHasCliCommand(identity, worker.cliPath, '__upgrade-worker', { allowMissingAbsolutePath: true }))
|
|
1821
|
+
throw new Error('The stalled upgrade worker identity changed unexpectedly.');
|
|
1822
|
+
}
|
|
1823
|
+
else if (worker.processGroupId !== worker.pid
|
|
1824
|
+
|| (await readProcessGroupMemberPids(worker.processGroupId)).length === 0) {
|
|
1825
|
+
return;
|
|
1826
|
+
}
|
|
1827
|
+
const signalOwnedWorker = (signalArg) => {
|
|
1828
|
+
try {
|
|
1829
|
+
process.kill(-worker.processGroupId, signalArg);
|
|
1830
|
+
}
|
|
1831
|
+
catch (errorArg) {
|
|
1832
|
+
if (errorArg.code !== 'ESRCH')
|
|
1833
|
+
throw errorArg;
|
|
1834
|
+
}
|
|
1835
|
+
};
|
|
1836
|
+
const waitForDrain = async () => {
|
|
1837
|
+
const deadline = Date.now() + workerTerminationGraceMs;
|
|
1838
|
+
while (Date.now() < deadline) {
|
|
1839
|
+
if ((await readProcessGroupMemberPids(worker.processGroupId)).length === 0)
|
|
1840
|
+
return true;
|
|
1841
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1842
|
+
}
|
|
1843
|
+
return (await readProcessGroupMemberPids(worker.processGroupId)).length === 0;
|
|
1844
|
+
};
|
|
1845
|
+
signalOwnedWorker('SIGTERM');
|
|
1846
|
+
if (await waitForDrain())
|
|
1847
|
+
return;
|
|
1848
|
+
signalOwnedWorker('SIGKILL');
|
|
1849
|
+
if (!await waitForDrain())
|
|
1850
|
+
throw new Error('The stalled upgrade worker group did not terminate.');
|
|
1851
|
+
}
|
|
1852
|
+
async readSanitizedUpgradeStatus(tokenArg) {
|
|
1853
|
+
const transaction = await this.readTransaction(tokenArg);
|
|
1854
|
+
if (!transaction.targetVersion)
|
|
1855
|
+
return undefined;
|
|
1856
|
+
if (transaction.retainedUntil !== undefined && transaction.retainedUntil < Date.now())
|
|
1857
|
+
return undefined;
|
|
1858
|
+
const phase = transaction.phase === 'starting'
|
|
1859
|
+
|| transaction.phase === 'checking'
|
|
1860
|
+
|| transaction.phase === 'stopping'
|
|
1861
|
+
? 'preparing'
|
|
1862
|
+
: transaction.phase;
|
|
1863
|
+
return {
|
|
1864
|
+
fromVersion: transaction.sourceVersion,
|
|
1865
|
+
toVersion: transaction.targetVersion,
|
|
1866
|
+
phase,
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1869
|
+
async finishTransaction(tokenArg, successArg, messageArg, errorArg) {
|
|
1870
|
+
return await this.mutateTransaction(tokenArg, (current) => {
|
|
1871
|
+
if (current.terminal)
|
|
1872
|
+
return current;
|
|
1873
|
+
return {
|
|
1874
|
+
...current,
|
|
1875
|
+
phase: successArg ? 'completed' : 'failed',
|
|
1876
|
+
message: assertBoundedText(messageArg, 'The upgrade terminal message', 4_096),
|
|
1877
|
+
retainedUntil: Date.now() + terminalStatusRetentionMs,
|
|
1878
|
+
terminal: {
|
|
1879
|
+
success: successArg,
|
|
1880
|
+
...(errorArg === undefined
|
|
1881
|
+
? {}
|
|
1882
|
+
: { error: assertBoundedText(errorArg, 'The upgrade terminal error', 4_096) }),
|
|
1883
|
+
},
|
|
1884
|
+
};
|
|
1885
|
+
});
|
|
1886
|
+
}
|
|
1887
|
+
async createLaunchGrant(optionsArg) {
|
|
1888
|
+
await this.init();
|
|
1889
|
+
if (typeof optionsArg.packageName !== 'string'
|
|
1890
|
+
|| optionsArg.packageName.length < 1
|
|
1891
|
+
|| optionsArg.packageName.length > 256
|
|
1892
|
+
|| typeof optionsArg.packageVersion !== 'string'
|
|
1893
|
+
|| optionsArg.packageVersion.length < 1
|
|
1894
|
+
|| optionsArg.packageVersion.length > 128
|
|
1895
|
+
|| !plugins.path.isAbsolute(optionsArg.cliPath)) {
|
|
1896
|
+
throw new Error(`The ${currentCliName} upgrade launch grant package binding is invalid.`);
|
|
1897
|
+
}
|
|
1898
|
+
const grant = {
|
|
1899
|
+
version: coordinationVersion,
|
|
1900
|
+
tokenHash: hashToken(optionsArg.token),
|
|
1901
|
+
expiresAt: Date.now() + 30_000,
|
|
1902
|
+
port: assertPort(optionsArg.port),
|
|
1903
|
+
packageName: optionsArg.packageName,
|
|
1904
|
+
packageVersion: optionsArg.packageVersion,
|
|
1905
|
+
cliPath: optionsArg.cliPath,
|
|
1906
|
+
controller: parseExpectedController(optionsArg.controller),
|
|
1907
|
+
};
|
|
1908
|
+
await writePrivateJson(this.tokenFilePath('grant', optionsArg.token), grant);
|
|
1909
|
+
}
|
|
1910
|
+
async removeLaunchGrant(tokenArg) {
|
|
1911
|
+
await plugins.fs.promises.unlink(this.tokenFilePath('grant', tokenArg)).catch((errorArg) => {
|
|
1912
|
+
if (errorArg.code !== 'ENOENT')
|
|
1913
|
+
throw errorArg;
|
|
1914
|
+
});
|
|
1915
|
+
await syncDirectory(this.baseDirectory);
|
|
1916
|
+
}
|
|
1917
|
+
async consumeLaunchGrant(optionsArg) {
|
|
1918
|
+
await this.init();
|
|
1919
|
+
const token = assertToken(optionsArg.token);
|
|
1920
|
+
const grantPath = this.tokenFilePath('grant', token);
|
|
1921
|
+
const consumedPath = `${grantPath}.consuming-${process.pid}-${plugins.crypto.randomBytes(4).toString('hex')}`;
|
|
1922
|
+
await plugins.fs.promises.rename(grantPath, consumedPath).catch((errorArg) => {
|
|
1923
|
+
if (errorArg.code === 'ENOENT') {
|
|
1924
|
+
throw new Error(`The ${currentCliName} upgrade launch grant is missing or already consumed.`);
|
|
1925
|
+
}
|
|
1926
|
+
throw errorArg;
|
|
1927
|
+
});
|
|
1928
|
+
try {
|
|
1929
|
+
const value = await readPrivateJson(consumedPath);
|
|
1930
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
1931
|
+
throw new Error(`The ${currentCliName} upgrade launch grant is malformed.`);
|
|
1932
|
+
}
|
|
1933
|
+
const grant = value;
|
|
1934
|
+
if (!exactKeys(grant, [
|
|
1935
|
+
'version',
|
|
1936
|
+
'tokenHash',
|
|
1937
|
+
'expiresAt',
|
|
1938
|
+
'port',
|
|
1939
|
+
'packageName',
|
|
1940
|
+
'packageVersion',
|
|
1941
|
+
'cliPath',
|
|
1942
|
+
'controller',
|
|
1943
|
+
])) {
|
|
1944
|
+
throw new Error(`The ${currentCliName} upgrade launch grant has unexpected fields.`);
|
|
1945
|
+
}
|
|
1946
|
+
const controller = parseExpectedController(grant.controller);
|
|
1947
|
+
const expected = parseExpectedController(optionsArg.controller);
|
|
1948
|
+
if (grant.version !== coordinationVersion
|
|
1949
|
+
|| typeof grant.expiresAt !== 'number'
|
|
1950
|
+
|| !Number.isSafeInteger(grant.expiresAt)
|
|
1951
|
+
|| grant.expiresAt < Date.now()
|
|
1952
|
+
|| grant.port !== assertPort(optionsArg.port)
|
|
1953
|
+
|| grant.packageName !== optionsArg.packageName
|
|
1954
|
+
|| grant.packageVersion !== optionsArg.packageVersion
|
|
1955
|
+
|| grant.cliPath !== optionsArg.cliPath
|
|
1956
|
+
|| controller.pid !== expected.pid
|
|
1957
|
+
|| controller.processGroupId !== expected.processGroupId
|
|
1958
|
+
|| controller.processFingerprint !== expected.processFingerprint
|
|
1959
|
+
|| typeof grant.tokenHash !== 'string'
|
|
1960
|
+
|| !upgradeTokenHashPattern.test(grant.tokenHash)
|
|
1961
|
+
|| !tokensEqual(grant.tokenHash, hashToken(token))) {
|
|
1962
|
+
throw new Error(`The ${currentCliName} upgrade launch grant binding is invalid or expired.`);
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
finally {
|
|
1966
|
+
await plugins.fs.promises.unlink(consumedPath).catch(() => undefined);
|
|
1967
|
+
await syncDirectory(this.baseDirectory);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
actionGrantFilePath(actionArg, tokenArg) {
|
|
1971
|
+
return plugins.path.join(this.baseDirectory, `action-${actionArg}-${coordinationPathHash(assertToken(tokenArg))}.json`);
|
|
1972
|
+
}
|
|
1973
|
+
async removeControllerActionGrant(actionArg, tokenArg) {
|
|
1974
|
+
await plugins.fs.promises.unlink(this.actionGrantFilePath(actionArg, tokenArg)).catch((errorArg) => {
|
|
1975
|
+
if (errorArg.code !== 'ENOENT')
|
|
1976
|
+
throw errorArg;
|
|
1977
|
+
});
|
|
1978
|
+
await syncDirectory(this.baseDirectory);
|
|
1979
|
+
}
|
|
1980
|
+
async createControllerActionGrant(optionsArg) {
|
|
1981
|
+
await this.init();
|
|
1982
|
+
if ((optionsArg.action === 'prepare' && optionsArg.mode !== undefined)
|
|
1983
|
+
|| (optionsArg.action === 'finalize' && optionsArg.mode === undefined))
|
|
1984
|
+
throw new Error('The upgrade controller action mode is invalid.');
|
|
1985
|
+
const grant = {
|
|
1986
|
+
version: coordinationVersion,
|
|
1987
|
+
tokenHash: hashToken(optionsArg.token),
|
|
1988
|
+
action: optionsArg.action,
|
|
1989
|
+
...(optionsArg.mode === undefined ? {} : { mode: optionsArg.mode }),
|
|
1990
|
+
expiresAt: Date.now() + 30_000,
|
|
1991
|
+
packageVersion: assertBoundedText(optionsArg.packageVersion, 'The upgrade action package version', 128),
|
|
1992
|
+
controller: parseExpectedController(optionsArg.controller),
|
|
1993
|
+
};
|
|
1994
|
+
await writePrivateJson(this.actionGrantFilePath(optionsArg.action, optionsArg.token), grant);
|
|
1995
|
+
}
|
|
1996
|
+
async consumeControllerActionGrant(optionsArg) {
|
|
1997
|
+
await this.init();
|
|
1998
|
+
const grantPath = this.actionGrantFilePath(optionsArg.action, optionsArg.token);
|
|
1999
|
+
const consumedPath = `${grantPath}.consuming-${process.pid}-${plugins.crypto.randomBytes(4).toString('hex')}`;
|
|
2000
|
+
await plugins.fs.promises.rename(grantPath, consumedPath).catch((errorArg) => {
|
|
2001
|
+
if (errorArg.code === 'ENOENT') {
|
|
2002
|
+
throw new Error('The upgrade controller action grant is missing or already consumed.');
|
|
2003
|
+
}
|
|
2004
|
+
throw errorArg;
|
|
2005
|
+
});
|
|
2006
|
+
try {
|
|
2007
|
+
const raw = await readPrivateJson(consumedPath);
|
|
2008
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
2009
|
+
throw new Error('The upgrade controller action grant is malformed.');
|
|
2010
|
+
}
|
|
2011
|
+
const grant = raw;
|
|
2012
|
+
const expectedController = parseExpectedController(optionsArg.controller);
|
|
2013
|
+
const controller = parseExpectedController(grant.controller);
|
|
2014
|
+
if (!exactKeys(grant, [
|
|
2015
|
+
'version', 'tokenHash', 'action', 'expiresAt', 'packageVersion', 'controller',
|
|
2016
|
+
...(grant.mode === undefined ? [] : ['mode']),
|
|
2017
|
+
])
|
|
2018
|
+
|| grant.version !== coordinationVersion
|
|
2019
|
+
|| grant.action !== optionsArg.action
|
|
2020
|
+
|| grant.mode !== optionsArg.mode
|
|
2021
|
+
|| !Number.isSafeInteger(grant.expiresAt)
|
|
2022
|
+
|| grant.expiresAt < Date.now()
|
|
2023
|
+
|| grant.packageVersion !== optionsArg.packageVersion
|
|
2024
|
+
|| controller.pid !== expectedController.pid
|
|
2025
|
+
|| controller.processGroupId !== expectedController.processGroupId
|
|
2026
|
+
|| controller.processFingerprint !== expectedController.processFingerprint
|
|
2027
|
+
|| typeof grant.tokenHash !== 'string'
|
|
2028
|
+
|| !tokensEqual(grant.tokenHash, hashToken(optionsArg.token)))
|
|
2029
|
+
throw new Error('The upgrade controller action grant binding is invalid or expired.');
|
|
2030
|
+
}
|
|
2031
|
+
finally {
|
|
2032
|
+
await plugins.fs.promises.unlink(consumedPath).catch(() => undefined);
|
|
2033
|
+
await syncDirectory(this.baseDirectory);
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
async acknowledgeWorker(tokenArg) {
|
|
2037
|
+
await this.init();
|
|
2038
|
+
const acknowledgement = {
|
|
2039
|
+
version: coordinationVersion,
|
|
2040
|
+
tokenHash: hashToken(tokenArg),
|
|
2041
|
+
};
|
|
2042
|
+
const acknowledgementPath = this.tokenFilePath('ack', tokenArg);
|
|
2043
|
+
try {
|
|
2044
|
+
await writePrivateJson(acknowledgementPath, acknowledgement);
|
|
2045
|
+
}
|
|
2046
|
+
catch (errorArg) {
|
|
2047
|
+
if (errorArg.code !== 'EEXIST')
|
|
2048
|
+
throw errorArg;
|
|
2049
|
+
const existing = await readPrivateJson(acknowledgementPath);
|
|
2050
|
+
if (!existing
|
|
2051
|
+
|| typeof existing !== 'object'
|
|
2052
|
+
|| Array.isArray(existing)
|
|
2053
|
+
|| !exactKeys(existing, ['version', 'tokenHash'])
|
|
2054
|
+
|| existing.version !== coordinationVersion
|
|
2055
|
+
|| existing.tokenHash !== acknowledgement.tokenHash)
|
|
2056
|
+
throw new Error('The existing upgrade acknowledgement is invalid.');
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
async waitForWorkerAcknowledgement(tokenArg, timeoutMsArg = 10_000) {
|
|
2060
|
+
const token = assertToken(tokenArg);
|
|
2061
|
+
const ackPath = this.tokenFilePath('ack', token);
|
|
2062
|
+
const deadline = Date.now() + timeoutMsArg;
|
|
2063
|
+
while (Date.now() < deadline) {
|
|
2064
|
+
try {
|
|
2065
|
+
const value = await readPrivateJson(ackPath);
|
|
2066
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
2067
|
+
throw new Error(`The ${currentCliName} upgrade acknowledgement is malformed.`);
|
|
2068
|
+
}
|
|
2069
|
+
const ack = value;
|
|
2070
|
+
if (!exactKeys(ack, ['version', 'tokenHash'])
|
|
2071
|
+
|| ack.version !== coordinationVersion
|
|
2072
|
+
|| typeof ack.tokenHash !== 'string'
|
|
2073
|
+
|| !upgradeTokenHashPattern.test(ack.tokenHash)
|
|
2074
|
+
|| !tokensEqual(ack.tokenHash, hashToken(token))) {
|
|
2075
|
+
throw new Error(`The ${currentCliName} upgrade acknowledgement binding is invalid.`);
|
|
2076
|
+
}
|
|
2077
|
+
await plugins.fs.promises.unlink(ackPath);
|
|
2078
|
+
await syncDirectory(this.baseDirectory);
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
catch (errorArg) {
|
|
2082
|
+
if (errorArg.code !== 'ENOENT')
|
|
2083
|
+
throw errorArg;
|
|
2084
|
+
}
|
|
2085
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2086
|
+
}
|
|
2087
|
+
throw new Error(`The ${currentCliName} upgrade caller did not acknowledge the detached worker.`);
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
export const createUpgradeToken = () => plugins.crypto
|
|
2091
|
+
.randomBytes(32)
|
|
2092
|
+
.toString('base64url');
|
|
2093
|
+
export const serializeUpgradeWorkerPayload = (payloadArg) => {
|
|
2094
|
+
assertToken(payloadArg.token);
|
|
2095
|
+
const payload = {
|
|
2096
|
+
version: coordinationVersion,
|
|
2097
|
+
port: assertPort(payloadArg.port),
|
|
2098
|
+
gracePeriodMs: payloadArg.gracePeriodMs,
|
|
2099
|
+
continueSessions: payloadArg.continueSessions,
|
|
2100
|
+
...(payloadArg.expectedController
|
|
2101
|
+
? { expectedController: parseExpectedController(payloadArg.expectedController) }
|
|
2102
|
+
: {}),
|
|
2103
|
+
};
|
|
2104
|
+
return Buffer.from(JSON.stringify(payload), 'utf8').toString('base64url');
|
|
2105
|
+
};
|
|
2106
|
+
export const parseUpgradeWorkerPayload = (payloadArg, tokenArg) => {
|
|
2107
|
+
if (typeof payloadArg !== 'string' || payloadArg.length < 8 || payloadArg.length > 4096) {
|
|
2108
|
+
throw new Error(`The ${currentCliName} upgrade worker payload is invalid.`);
|
|
2109
|
+
}
|
|
2110
|
+
let value;
|
|
2111
|
+
try {
|
|
2112
|
+
value = JSON.parse(Buffer.from(payloadArg, 'base64url').toString('utf8'));
|
|
2113
|
+
}
|
|
2114
|
+
catch {
|
|
2115
|
+
throw new Error(`The ${currentCliName} upgrade worker payload is malformed.`);
|
|
2116
|
+
}
|
|
2117
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
2118
|
+
throw new Error(`The ${currentCliName} upgrade worker payload is malformed.`);
|
|
2119
|
+
}
|
|
2120
|
+
const payload = value;
|
|
2121
|
+
if (!exactKeys(payload, [
|
|
2122
|
+
'version',
|
|
2123
|
+
'port',
|
|
2124
|
+
'gracePeriodMs',
|
|
2125
|
+
'continueSessions',
|
|
2126
|
+
...(payload.expectedController === undefined ? [] : ['expectedController']),
|
|
2127
|
+
])) {
|
|
2128
|
+
throw new Error(`The ${currentCliName} upgrade worker payload has unexpected fields.`);
|
|
2129
|
+
}
|
|
2130
|
+
if (payload.version !== coordinationVersion) {
|
|
2131
|
+
throw new Error(`The ${currentCliName} upgrade worker payload version is unsupported.`);
|
|
2132
|
+
}
|
|
2133
|
+
return {
|
|
2134
|
+
version: coordinationVersion,
|
|
2135
|
+
token: assertToken(tokenArg),
|
|
2136
|
+
port: assertPort(payload.port),
|
|
2137
|
+
gracePeriodMs: (() => {
|
|
2138
|
+
if (!Number.isSafeInteger(payload.gracePeriodMs)
|
|
2139
|
+
|| payload.gracePeriodMs < 1_000
|
|
2140
|
+
|| payload.gracePeriodMs > 60 * 60 * 1000)
|
|
2141
|
+
throw new Error(`The ${currentCliName} upgrade grace period is invalid.`);
|
|
2142
|
+
return payload.gracePeriodMs;
|
|
2143
|
+
})(),
|
|
2144
|
+
continueSessions: (() => {
|
|
2145
|
+
if (typeof payload.continueSessions !== 'boolean') {
|
|
2146
|
+
throw new Error(`The ${currentCliName} upgrade continuation option is invalid.`);
|
|
2147
|
+
}
|
|
2148
|
+
return payload.continueSessions;
|
|
2149
|
+
})(),
|
|
2150
|
+
...(payload.expectedController
|
|
2151
|
+
? { expectedController: parseExpectedController(payload.expectedController) }
|
|
2152
|
+
: {}),
|
|
2153
|
+
};
|
|
2154
|
+
};
|
|
2155
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy51cGdyYWRlY29vcmRpbmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9jbGFzc2VzLnVwZ3JhZGVjb29yZGluYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQ0wscUJBQXFCLEdBR3RCLE1BQU0sMkJBQTJCLENBQUM7QUFDbkMsT0FBTyxFQUNMLDRCQUE0QixFQUM1Qiw2QkFBNkIsRUFDN0IsMEJBQTBCLEdBQzNCLE1BQU0sZ0NBQWdDLENBQUM7QUFFeEMsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUcsQ0FBVSxDQUFDO0FBQ3JELE1BQU0sbUJBQW1CLEdBQUcsMEJBQTBCLENBQUM7QUFDdkQsTUFBTSxDQUFDLE1BQU0sMENBQTBDLEdBQUcsQ0FBVSxDQUFDO0FBQ3JFLE1BQU0sQ0FBQyxNQUFNLDhCQUE4QixHQUFHO0lBQzVDLFdBQVcsRUFBRSxzQ0FBc0M7SUFDbkQsT0FBTyxFQUFFLFFBQVE7SUFDakIsaUJBQWlCLEVBQUUsQ0FBQztJQUNwQixPQUFPLEVBQUUsTUFBTTtJQUNmLGVBQWUsRUFBRSxVQUFVO0NBQ25CLENBQUM7QUFDWCxNQUFNLENBQUMsTUFBTSw4QkFBOEIsR0FBRztJQUM1QyxXQUFXLEVBQUUsS0FBSztJQUNsQixPQUFPLEVBQUUsUUFBUTtJQUNqQixpQkFBaUIsRUFBRSxDQUFDO0lBQ3BCLE9BQU8sRUFBRSxLQUFLO0lBQ2QsZUFBZSxFQUFFLFVBQVU7Q0FDbkIsQ0FBQztBQUNYLE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLDhCQUE4QixDQUFDLFdBQVc7SUFDakcsQ0FBQyxDQUFDLDhCQUE4QixDQUFDLE9BQU87SUFDeEMsQ0FBQyxDQUFDLDhCQUE4QixDQUFDLE9BQU8sQ0FBQztBQUMzQyxNQUFNLGFBQWEsR0FBRyxZQUFZLENBQUM7QUFDbkMsTUFBTSxvQkFB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
|