@rogatio/cli 6.16.5 → 6.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +345 -93
- package/package.json +4 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cli(args?: string[]): Promise<number>;
|
package/dist/node/index.js
CHANGED
|
@@ -22598,6 +22598,15 @@ function defaultTrustInstallRoot(platform) {
|
|
|
22598
22598
|
}
|
|
22599
22599
|
return join2(process.env.HOME ?? "", ".local", "share", "rogatio");
|
|
22600
22600
|
}
|
|
22601
|
+
var MANIFEST_DIR_RECORD = "native-messaging-dirs.json";
|
|
22602
|
+
function isSafeManifestDir(dir) {
|
|
22603
|
+
if (!isAbsolute2(dir) || dir.includes("\0")) return false;
|
|
22604
|
+
const parts = dir.split(/[\\/]/).filter((part) => part.length > 0);
|
|
22605
|
+
if (parts.includes("..") || parts.length < 2) return false;
|
|
22606
|
+
const browser = parts[parts.length - 2];
|
|
22607
|
+
const leaf = parts[parts.length - 1];
|
|
22608
|
+
return leaf === "NativeMessagingHosts" && (browser === "google-chrome" || browser === "chromium");
|
|
22609
|
+
}
|
|
22601
22610
|
function isWellFormedManifest(value) {
|
|
22602
22611
|
if (typeof value !== "object" || value === null) return false;
|
|
22603
22612
|
const m = value;
|
|
@@ -22754,12 +22763,110 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22754
22763
|
installRoot,
|
|
22755
22764
|
options.caCertFileName ?? ".rogatio-ca.crt"
|
|
22756
22765
|
);
|
|
22766
|
+
const storePendingPath = join2(
|
|
22767
|
+
dirname2(caKeyFile),
|
|
22768
|
+
".rogatio-ca-store-pending"
|
|
22769
|
+
);
|
|
22757
22770
|
const caPreviousCertFile = join2(
|
|
22758
22771
|
dirname2(caCertFile),
|
|
22759
22772
|
".rogatio-ca.previous.crt"
|
|
22760
22773
|
);
|
|
22761
|
-
const
|
|
22774
|
+
const configuredManifestDirs = options.manifestDirs && options.manifestDirs.length > 0 ? [...options.manifestDirs] : [manifestDir];
|
|
22775
|
+
const recordsManifestDirs = options.manifestDirs !== void 0 && options.manifestDirs.length > 0;
|
|
22776
|
+
const manifestRecordPath = join2(installRoot, MANIFEST_DIR_RECORD);
|
|
22762
22777
|
let installerCalled = false;
|
|
22778
|
+
function parseRecordedDirs(raw) {
|
|
22779
|
+
let parsed;
|
|
22780
|
+
try {
|
|
22781
|
+
parsed = JSON.parse(raw);
|
|
22782
|
+
} catch {
|
|
22783
|
+
return void 0;
|
|
22784
|
+
}
|
|
22785
|
+
if (!Array.isArray(parsed) || parsed.length === 0 || parsed.length > 8) {
|
|
22786
|
+
return void 0;
|
|
22787
|
+
}
|
|
22788
|
+
const dirs = [];
|
|
22789
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22790
|
+
for (const entry of parsed) {
|
|
22791
|
+
if (typeof entry !== "string" || seen.has(entry) || !isSafeManifestDir(entry)) {
|
|
22792
|
+
return void 0;
|
|
22793
|
+
}
|
|
22794
|
+
seen.add(entry);
|
|
22795
|
+
dirs.push(entry);
|
|
22796
|
+
}
|
|
22797
|
+
return dirs;
|
|
22798
|
+
}
|
|
22799
|
+
async function readRecordedDirs() {
|
|
22800
|
+
if (!recordsManifestDirs) return void 0;
|
|
22801
|
+
try {
|
|
22802
|
+
return parseRecordedDirs(await readFile2(manifestRecordPath, "utf8"));
|
|
22803
|
+
} catch {
|
|
22804
|
+
return void 0;
|
|
22805
|
+
}
|
|
22806
|
+
}
|
|
22807
|
+
async function activeManifestDirs() {
|
|
22808
|
+
const recorded = await readRecordedDirs();
|
|
22809
|
+
if (recorded) return recorded;
|
|
22810
|
+
if (!recordsManifestDirs) return configuredManifestDirs;
|
|
22811
|
+
const present = [];
|
|
22812
|
+
for (const dir of configuredManifestDirs) {
|
|
22813
|
+
if (await existsFile(join2(dir, `${hostName}.json`))) present.push(dir);
|
|
22814
|
+
}
|
|
22815
|
+
return present.length > 0 ? present : configuredManifestDirs;
|
|
22816
|
+
}
|
|
22817
|
+
async function snapshotFile(path2) {
|
|
22818
|
+
let previous;
|
|
22819
|
+
try {
|
|
22820
|
+
previous = await readFile2(path2, "utf8");
|
|
22821
|
+
} catch {
|
|
22822
|
+
previous = void 0;
|
|
22823
|
+
}
|
|
22824
|
+
return { path: path2, previous, written: false };
|
|
22825
|
+
}
|
|
22826
|
+
async function restoreSnapshot(snap) {
|
|
22827
|
+
if (!snap.written) return;
|
|
22828
|
+
if (snap.previous !== void 0) {
|
|
22829
|
+
await writeFileAtomic(snap.path, snap.previous);
|
|
22830
|
+
return;
|
|
22831
|
+
}
|
|
22832
|
+
await rm(snap.path, { force: true });
|
|
22833
|
+
}
|
|
22834
|
+
async function rollbackWritten(snaps) {
|
|
22835
|
+
for (const snap of snaps) {
|
|
22836
|
+
try {
|
|
22837
|
+
await restoreSnapshot(snap);
|
|
22838
|
+
} catch {
|
|
22839
|
+
}
|
|
22840
|
+
}
|
|
22841
|
+
}
|
|
22842
|
+
async function writeManifestFiles(data) {
|
|
22843
|
+
const snaps = [];
|
|
22844
|
+
try {
|
|
22845
|
+
for (const dir of configuredManifestDirs) {
|
|
22846
|
+
if (recordsManifestDirs && !isSafeManifestDir(dir)) {
|
|
22847
|
+
throw new Error("trust.write-failed");
|
|
22848
|
+
}
|
|
22849
|
+
const snap = await snapshotFile(join2(dir, `${hostName}.json`));
|
|
22850
|
+
snaps.push(snap);
|
|
22851
|
+
await writeFileAtomic(snap.path, data);
|
|
22852
|
+
snap.written = true;
|
|
22853
|
+
}
|
|
22854
|
+
if (recordsManifestDirs) {
|
|
22855
|
+
const recordSnap = await snapshotFile(manifestRecordPath);
|
|
22856
|
+
snaps.push(recordSnap);
|
|
22857
|
+
await writeFileAtomic(
|
|
22858
|
+
manifestRecordPath,
|
|
22859
|
+
`${JSON.stringify(configuredManifestDirs)}
|
|
22860
|
+
`
|
|
22861
|
+
);
|
|
22862
|
+
recordSnap.written = true;
|
|
22863
|
+
}
|
|
22864
|
+
return { ok: true, snaps };
|
|
22865
|
+
} catch (error) {
|
|
22866
|
+
await rollbackWritten(snaps);
|
|
22867
|
+
return { ok: false, reason: codeOf(error, "trust.write-failed") };
|
|
22868
|
+
}
|
|
22869
|
+
}
|
|
22763
22870
|
async function install(extensionId) {
|
|
22764
22871
|
if (!extensionId || !/^[a-p]{32}$/.test(extensionId)) {
|
|
22765
22872
|
return {
|
|
@@ -22794,21 +22901,17 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22794
22901
|
}
|
|
22795
22902
|
const caps = await detect();
|
|
22796
22903
|
if (!caps.manifest) return unsupportedResult(caps);
|
|
22797
|
-
|
|
22798
|
-
|
|
22799
|
-
} catch (error) {
|
|
22904
|
+
const written = await writeManifestFiles(data);
|
|
22905
|
+
if (!written.ok) {
|
|
22800
22906
|
return {
|
|
22801
22907
|
ok: false,
|
|
22802
22908
|
state: "unsupported",
|
|
22803
|
-
reasons: [
|
|
22909
|
+
reasons: [written.reason]
|
|
22804
22910
|
};
|
|
22805
22911
|
}
|
|
22806
22912
|
const caTrustCaps = await detect();
|
|
22807
22913
|
if (!caTrustCaps.caTrust) {
|
|
22808
|
-
|
|
22809
|
-
await rm(manifestPath(), { force: true });
|
|
22810
|
-
} catch {
|
|
22811
|
-
}
|
|
22914
|
+
await rollbackWritten(written.snaps);
|
|
22812
22915
|
return unsupportedResult(caTrustCaps);
|
|
22813
22916
|
}
|
|
22814
22917
|
const trustResult = await trust();
|
|
@@ -22817,13 +22920,11 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22817
22920
|
await rollbackReplacedCa();
|
|
22818
22921
|
} catch {
|
|
22819
22922
|
}
|
|
22820
|
-
|
|
22821
|
-
await rm(manifestPath(), { force: true });
|
|
22822
|
-
} catch {
|
|
22823
|
-
}
|
|
22923
|
+
await rollbackWritten(written.snaps);
|
|
22824
22924
|
installerCalled = false;
|
|
22825
22925
|
return trustResult;
|
|
22826
22926
|
}
|
|
22927
|
+
await rm(storePendingPath, { force: true });
|
|
22827
22928
|
return trustResult.reasons ? { ok: true, state: "installed", reasons: trustResult.reasons } : { ok: true, state: "installed" };
|
|
22828
22929
|
}
|
|
22829
22930
|
async function reusableCaMaterial() {
|
|
@@ -22953,8 +23054,8 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22953
23054
|
}
|
|
22954
23055
|
let installedNew = false;
|
|
22955
23056
|
if (caTrustInstaller && !installerCalled) {
|
|
22956
|
-
await caTrustInstaller(await readFile2(caCertFile, "utf8"));
|
|
22957
23057
|
installerCalled = true;
|
|
23058
|
+
await caTrustInstaller(await readFile2(caCertFile, "utf8"));
|
|
22958
23059
|
installedNew = true;
|
|
22959
23060
|
}
|
|
22960
23061
|
if (reusable && siblingAnchor && (installedNew || !caTrustInstaller)) {
|
|
@@ -22979,11 +23080,15 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22979
23080
|
const saved = await readPreviousRogatioCa(caPreviousCertFile);
|
|
22980
23081
|
const live = await readPreviousRogatioCa(caCertFile);
|
|
22981
23082
|
const caWasPresent = await existsFile(caKeyFile);
|
|
23083
|
+
if (caWasPresent && caTrustRemover) {
|
|
23084
|
+
await writeFileAtomic(storePendingPath, "1\n", 384);
|
|
23085
|
+
}
|
|
22982
23086
|
await rm(caKeyFile, { force: true });
|
|
22983
23087
|
await rm(caPubFile, { force: true });
|
|
22984
23088
|
await rm(caCertFile, { force: true });
|
|
22985
|
-
if (
|
|
23089
|
+
if (caTrustRemover && await existsFile(storePendingPath)) {
|
|
22986
23090
|
await caTrustRemover();
|
|
23091
|
+
await rm(storePendingPath, { force: true });
|
|
22987
23092
|
}
|
|
22988
23093
|
if (!saved) return;
|
|
22989
23094
|
if (!caWasPresent || saved.fingerprint !== live?.fingerprint) {
|
|
@@ -22998,14 +23103,19 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22998
23103
|
}
|
|
22999
23104
|
async function uninstall() {
|
|
23000
23105
|
try {
|
|
23001
|
-
|
|
23106
|
+
const dirs = await activeManifestDirs();
|
|
23107
|
+
for (const dir of dirs) {
|
|
23108
|
+
await rm(join2(dir, `${hostName}.json`), { force: true });
|
|
23109
|
+
}
|
|
23110
|
+
if (recordsManifestDirs) await rm(manifestRecordPath, { force: true });
|
|
23002
23111
|
await removeCa();
|
|
23003
23112
|
installerCalled = false;
|
|
23004
23113
|
} catch (error) {
|
|
23114
|
+
const reason = error instanceof TrustError ? error.message : error instanceof Error ? error.message : String(error);
|
|
23005
23115
|
return {
|
|
23006
23116
|
ok: false,
|
|
23007
23117
|
state: "unsupported",
|
|
23008
|
-
reasons: [
|
|
23118
|
+
reasons: [reason]
|
|
23009
23119
|
};
|
|
23010
23120
|
}
|
|
23011
23121
|
return { ok: true, state: "uninstalled" };
|
|
@@ -23022,13 +23132,30 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
23022
23132
|
}
|
|
23023
23133
|
return anchorRemovalWarning ? { ok: true, state: "trusted", reasons: [anchorRemovalWarning] } : { ok: true, state: "trusted" };
|
|
23024
23134
|
}
|
|
23135
|
+
function manifestAcceptable(parsed) {
|
|
23136
|
+
if (!recordsManifestDirs) return true;
|
|
23137
|
+
return parsed.name === hostName && parsed.path === hostPath && parsed.type === "stdio";
|
|
23138
|
+
}
|
|
23139
|
+
function sameOrigins(left, right) {
|
|
23140
|
+
if (left.length !== right.length) return false;
|
|
23141
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
23142
|
+
if (left[index] !== right[index]) return false;
|
|
23143
|
+
}
|
|
23144
|
+
return true;
|
|
23145
|
+
}
|
|
23025
23146
|
async function status() {
|
|
23026
|
-
|
|
23027
|
-
|
|
23028
|
-
|
|
23029
|
-
|
|
23030
|
-
|
|
23031
|
-
|
|
23147
|
+
const dirs = await activeManifestDirs();
|
|
23148
|
+
let installed = dirs.length > 0;
|
|
23149
|
+
for (const dir of dirs) {
|
|
23150
|
+
try {
|
|
23151
|
+
const raw = await readFile2(join2(dir, `${hostName}.json`), "utf8");
|
|
23152
|
+
const parsed = JSON.parse(raw);
|
|
23153
|
+
if (!isWellFormedManifest(parsed) || !manifestAcceptable(parsed)) {
|
|
23154
|
+
installed = false;
|
|
23155
|
+
}
|
|
23156
|
+
} catch {
|
|
23157
|
+
installed = false;
|
|
23158
|
+
}
|
|
23032
23159
|
}
|
|
23033
23160
|
const trusted = await existsFile(caKeyFile) && await existsFile(caCertFile);
|
|
23034
23161
|
const caps = await detect();
|
|
@@ -23041,34 +23168,50 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
23041
23168
|
}
|
|
23042
23169
|
async function verify2() {
|
|
23043
23170
|
const reasons = [];
|
|
23044
|
-
|
|
23045
|
-
|
|
23171
|
+
const pushReason = (reason) => {
|
|
23172
|
+
if (!reasons.includes(reason)) reasons.push(reason);
|
|
23173
|
+
};
|
|
23174
|
+
const dirs = await activeManifestDirs();
|
|
23175
|
+
let manifestExists = dirs.length > 0;
|
|
23176
|
+
let manifestValid = dirs.length > 0;
|
|
23046
23177
|
let binaryExists = false;
|
|
23047
23178
|
let binaryExecutable = false;
|
|
23048
23179
|
let allowedOrigins = [];
|
|
23049
|
-
|
|
23050
|
-
|
|
23051
|
-
|
|
23052
|
-
|
|
23053
|
-
|
|
23054
|
-
|
|
23055
|
-
|
|
23056
|
-
|
|
23057
|
-
|
|
23058
|
-
binaryExists = fileStat.isFile();
|
|
23059
|
-
binaryExecutable = platform === "win32" ? binaryExists : (fileStat.mode & 73) !== 0;
|
|
23060
|
-
if (!binaryExists) reasons.push("binary-not-found");
|
|
23061
|
-
if (!binaryExecutable) reasons.push("binary-not-executable");
|
|
23062
|
-
} catch {
|
|
23063
|
-
binaryExists = false;
|
|
23064
|
-
reasons.push("binary-not-found");
|
|
23180
|
+
let binaryPath;
|
|
23181
|
+
for (const dir of dirs) {
|
|
23182
|
+
try {
|
|
23183
|
+
const raw = await readFile2(join2(dir, `${hostName}.json`), "utf8");
|
|
23184
|
+
const parsed = JSON.parse(raw);
|
|
23185
|
+
if (!isWellFormedManifest(parsed) || !manifestAcceptable(parsed)) {
|
|
23186
|
+
manifestValid = false;
|
|
23187
|
+
pushReason("manifest-invalid");
|
|
23188
|
+
continue;
|
|
23065
23189
|
}
|
|
23066
|
-
if (
|
|
23067
|
-
|
|
23068
|
-
|
|
23190
|
+
if (binaryPath === void 0) {
|
|
23191
|
+
binaryPath = parsed.path;
|
|
23192
|
+
allowedOrigins = [...parsed.allowed_origins];
|
|
23193
|
+
} else if (parsed.path !== binaryPath || !sameOrigins(parsed.allowed_origins, allowedOrigins)) {
|
|
23194
|
+
manifestValid = false;
|
|
23195
|
+
pushReason("manifest-invalid");
|
|
23196
|
+
}
|
|
23197
|
+
} catch {
|
|
23198
|
+
manifestExists = false;
|
|
23199
|
+
manifestValid = false;
|
|
23200
|
+
pushReason("manifest-not-found");
|
|
23069
23201
|
}
|
|
23070
|
-
}
|
|
23071
|
-
|
|
23202
|
+
}
|
|
23203
|
+
if (binaryPath !== void 0) {
|
|
23204
|
+
try {
|
|
23205
|
+
const fileStat = await stat(binaryPath);
|
|
23206
|
+
binaryExists = fileStat.isFile();
|
|
23207
|
+
binaryExecutable = platform === "win32" ? binaryExists : (fileStat.mode & 73) !== 0;
|
|
23208
|
+
if (!binaryExists) pushReason("binary-not-found");
|
|
23209
|
+
if (!binaryExecutable) pushReason("binary-not-executable");
|
|
23210
|
+
} catch {
|
|
23211
|
+
binaryExists = false;
|
|
23212
|
+
pushReason("binary-not-found");
|
|
23213
|
+
}
|
|
23214
|
+
if (allowedOrigins.length === 0) pushReason("no-allowed-origins");
|
|
23072
23215
|
}
|
|
23073
23216
|
const caTrusted = await existsFile(caKeyFile) && await existsFile(caCertFile);
|
|
23074
23217
|
if (!caTrusted) reasons.push("ca-not-trusted");
|
|
@@ -23261,10 +23404,99 @@ var darwinAdapter = {
|
|
|
23261
23404
|
};
|
|
23262
23405
|
var darwin_default = darwinAdapter;
|
|
23263
23406
|
var CA_DIR = "/usr/local/share/ca-certificates";
|
|
23264
|
-
var
|
|
23265
|
-
|
|
23266
|
-
|
|
23267
|
-
|
|
23407
|
+
var CERT_NAME = "rogatio-ca.crt";
|
|
23408
|
+
var DEBIAN_CERT = posixJoin2(CA_DIR, CERT_NAME);
|
|
23409
|
+
var ARCH_TRUST_SOURCE = "/etc/ca-certificates/trust-source";
|
|
23410
|
+
var FEDORA_TRUST_SOURCE = "/etc/pki/ca-trust/source";
|
|
23411
|
+
var ARCH_ANCHORS = "/etc/ca-certificates/trust-source/anchors";
|
|
23412
|
+
var FEDORA_ANCHORS = "/etc/pki/ca-trust/source/anchors";
|
|
23413
|
+
var P11_CERTS = [
|
|
23414
|
+
posixJoin2(ARCH_ANCHORS, CERT_NAME),
|
|
23415
|
+
posixJoin2(FEDORA_ANCHORS, CERT_NAME)
|
|
23416
|
+
];
|
|
23417
|
+
var BROWSERS = ["google-chrome", "chromium"];
|
|
23418
|
+
function nodeCode(err) {
|
|
23419
|
+
const code = err?.code;
|
|
23420
|
+
return typeof code === "string" && code.length > 0 ? code : "EACCES";
|
|
23421
|
+
}
|
|
23422
|
+
function exists(path2) {
|
|
23423
|
+
try {
|
|
23424
|
+
accessSync2(path2);
|
|
23425
|
+
return true;
|
|
23426
|
+
} catch (err) {
|
|
23427
|
+
return nodeCode(err) !== "ENOENT";
|
|
23428
|
+
}
|
|
23429
|
+
}
|
|
23430
|
+
function writable(path2) {
|
|
23431
|
+
try {
|
|
23432
|
+
accessSync2(path2, constants3.W_OK);
|
|
23433
|
+
return true;
|
|
23434
|
+
} catch {
|
|
23435
|
+
return false;
|
|
23436
|
+
}
|
|
23437
|
+
}
|
|
23438
|
+
function toolOnPath(name) {
|
|
23439
|
+
const result = spawnSync2("which", [name], { timeout: 1e3 });
|
|
23440
|
+
if (result.status === 0) return true;
|
|
23441
|
+
const code = result.error?.code;
|
|
23442
|
+
if (code !== "ENOENT") return false;
|
|
23443
|
+
const pathEnv = process.env.PATH ?? "";
|
|
23444
|
+
for (const dir of pathEnv.split(":")) {
|
|
23445
|
+
if (dir.length === 0) continue;
|
|
23446
|
+
try {
|
|
23447
|
+
accessSync2(posixJoin2(dir, name));
|
|
23448
|
+
return true;
|
|
23449
|
+
} catch {
|
|
23450
|
+
}
|
|
23451
|
+
}
|
|
23452
|
+
return false;
|
|
23453
|
+
}
|
|
23454
|
+
function caBackend() {
|
|
23455
|
+
if (toolOnPath("update-ca-certificates")) return "debian";
|
|
23456
|
+
if (toolOnPath("update-ca-trust")) return "p11kit";
|
|
23457
|
+
return void 0;
|
|
23458
|
+
}
|
|
23459
|
+
function p11kitAnchorsDir() {
|
|
23460
|
+
const arch = exists(ARCH_TRUST_SOURCE);
|
|
23461
|
+
const fedora = exists(FEDORA_TRUST_SOURCE);
|
|
23462
|
+
if (arch && !fedora) return ARCH_ANCHORS;
|
|
23463
|
+
if (fedora && !arch) return FEDORA_ANCHORS;
|
|
23464
|
+
return void 0;
|
|
23465
|
+
}
|
|
23466
|
+
function needsElevation(dir) {
|
|
23467
|
+
if (writable(dir)) return false;
|
|
23468
|
+
try {
|
|
23469
|
+
accessSync2(dir, constants3.W_OK);
|
|
23470
|
+
} catch (err) {
|
|
23471
|
+
if (nodeCode(err) === "ENOENT" && writable(dirname4(dir))) return false;
|
|
23472
|
+
}
|
|
23473
|
+
return !toolOnPath("sudo");
|
|
23474
|
+
}
|
|
23475
|
+
function configHome() {
|
|
23476
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
23477
|
+
if (typeof xdg === "string" && xdg.startsWith("/")) return xdg;
|
|
23478
|
+
const home = process.env.HOME ?? "";
|
|
23479
|
+
return posixJoin2(home, ".config");
|
|
23480
|
+
}
|
|
23481
|
+
function manifestDirFor(browser) {
|
|
23482
|
+
return posixJoin2(configHome(), browser, "NativeMessagingHosts");
|
|
23483
|
+
}
|
|
23484
|
+
function canHostManifest(dir) {
|
|
23485
|
+
try {
|
|
23486
|
+
accessSync2(dir, constants3.W_OK);
|
|
23487
|
+
return true;
|
|
23488
|
+
} catch (err) {
|
|
23489
|
+
if (nodeCode(err) !== "ENOENT") return false;
|
|
23490
|
+
}
|
|
23491
|
+
try {
|
|
23492
|
+
accessSync2(dirname4(dir), constants3.W_OK);
|
|
23493
|
+
return true;
|
|
23494
|
+
} catch {
|
|
23495
|
+
return false;
|
|
23496
|
+
}
|
|
23497
|
+
}
|
|
23498
|
+
function installableManifestDirs() {
|
|
23499
|
+
return BROWSERS.map(manifestDirFor).filter(canHostManifest);
|
|
23268
23500
|
}
|
|
23269
23501
|
function installFailureReason(stderr) {
|
|
23270
23502
|
const text = stderr.toLowerCase();
|
|
@@ -23306,44 +23538,36 @@ function runSudo(args, stdin) {
|
|
|
23306
23538
|
input.end(stdin);
|
|
23307
23539
|
});
|
|
23308
23540
|
}
|
|
23541
|
+
async function sudoOrThrow(args, stdin) {
|
|
23542
|
+
const result = await runSudo(args, stdin);
|
|
23543
|
+
if (result.code === 0) return;
|
|
23544
|
+
const reason = installFailureReason(result.stderr);
|
|
23545
|
+
throw new TrustError("trust.internal", reason, [reason]);
|
|
23546
|
+
}
|
|
23309
23547
|
var linuxAdapter = {
|
|
23310
23548
|
platform: "linux",
|
|
23311
23549
|
defaultManifestDir: () => {
|
|
23312
23550
|
const home = process.env.HOME ?? "";
|
|
23313
23551
|
return posixJoin2(home, ".config/google-chrome/NativeMessagingHosts");
|
|
23314
23552
|
},
|
|
23553
|
+
manifestDirs: () => installableManifestDirs(),
|
|
23315
23554
|
defaultCaInstallPath: () => CA_DIR,
|
|
23316
23555
|
detect() {
|
|
23317
23556
|
const reasons = [];
|
|
23318
|
-
const
|
|
23319
|
-
|
|
23320
|
-
|
|
23321
|
-
});
|
|
23322
|
-
if (updateCa.status !== 0) {
|
|
23323
|
-
reasons.push("tooling-missing");
|
|
23324
|
-
}
|
|
23325
|
-
try {
|
|
23326
|
-
accessSync2(manifestDir, constants3.W_OK);
|
|
23327
|
-
} catch {
|
|
23557
|
+
const backend = caBackend();
|
|
23558
|
+
if (!backend) reasons.push("tooling-missing");
|
|
23559
|
+
if (installableManifestDirs().length === 0) {
|
|
23328
23560
|
reasons.push("manifest-dir-unwritable");
|
|
23329
23561
|
}
|
|
23330
|
-
|
|
23331
|
-
|
|
23332
|
-
}
|
|
23333
|
-
|
|
23334
|
-
|
|
23335
|
-
|
|
23336
|
-
} catch {
|
|
23337
|
-
if (!hasSudo()) {
|
|
23338
|
-
reasons.push("elevation-required");
|
|
23339
|
-
}
|
|
23340
|
-
}
|
|
23341
|
-
} else if (!hasSudo()) {
|
|
23342
|
-
reasons.push("elevation-required");
|
|
23343
|
-
}
|
|
23562
|
+
if (backend === "debian") {
|
|
23563
|
+
if (needsElevation(CA_DIR)) reasons.push("elevation-required");
|
|
23564
|
+
} else if (backend === "p11kit") {
|
|
23565
|
+
const anchors = p11kitAnchorsDir();
|
|
23566
|
+
if (!anchors) reasons.push("ca-store-unwritable");
|
|
23567
|
+
else if (needsElevation(anchors)) reasons.push("elevation-required");
|
|
23344
23568
|
}
|
|
23345
23569
|
const manifest = !reasons.includes("tooling-missing") && !reasons.includes("manifest-dir-unwritable");
|
|
23346
|
-
const caTrust = !reasons.includes("tooling-missing") && !reasons.includes("elevation-required");
|
|
23570
|
+
const caTrust = !reasons.includes("tooling-missing") && !reasons.includes("elevation-required") && !reasons.includes("ca-store-unwritable");
|
|
23347
23571
|
return {
|
|
23348
23572
|
manifest,
|
|
23349
23573
|
caTrust,
|
|
@@ -23356,29 +23580,55 @@ var linuxAdapter = {
|
|
|
23356
23580
|
"invalid-ca-certificate"
|
|
23357
23581
|
]);
|
|
23358
23582
|
}
|
|
23359
|
-
|
|
23360
|
-
|
|
23361
|
-
|
|
23583
|
+
if (caBackend() === "debian") {
|
|
23584
|
+
try {
|
|
23585
|
+
mkdirSync(CA_DIR, { recursive: true });
|
|
23586
|
+
} catch {
|
|
23587
|
+
throw new TrustError("trust.internal", "ca-store-unwritable", [
|
|
23588
|
+
"ca-store-unwritable"
|
|
23589
|
+
]);
|
|
23590
|
+
}
|
|
23591
|
+
await sudoOrThrow(["tee", DEBIAN_CERT], certPem);
|
|
23592
|
+
await sudoOrThrow(["update-ca-certificates"]);
|
|
23593
|
+
return;
|
|
23594
|
+
}
|
|
23595
|
+
if (caBackend() !== "p11kit") {
|
|
23596
|
+
throw new TrustError("trust.internal", "tooling-missing", [
|
|
23597
|
+
"tooling-missing"
|
|
23598
|
+
]);
|
|
23599
|
+
}
|
|
23600
|
+
const anchors = p11kitAnchorsDir();
|
|
23601
|
+
if (!anchors) {
|
|
23362
23602
|
throw new TrustError("trust.internal", "ca-store-unwritable", [
|
|
23363
23603
|
"ca-store-unwritable"
|
|
23364
23604
|
]);
|
|
23365
23605
|
}
|
|
23366
|
-
const
|
|
23367
|
-
|
|
23368
|
-
|
|
23369
|
-
|
|
23370
|
-
|
|
23371
|
-
|
|
23372
|
-
|
|
23373
|
-
|
|
23374
|
-
|
|
23375
|
-
|
|
23606
|
+
const certPath = posixJoin2(anchors, CERT_NAME);
|
|
23607
|
+
await sudoOrThrow(["mkdir", "-p", anchors]);
|
|
23608
|
+
await sudoOrThrow(["tee", certPath], certPem);
|
|
23609
|
+
const refresh = await runSudo(["update-ca-trust"]);
|
|
23610
|
+
if (refresh.code === 0) return;
|
|
23611
|
+
await sudoOrThrow(["rm", "-f", certPath]);
|
|
23612
|
+
const rebuilt = await runSudo(["update-ca-trust"]);
|
|
23613
|
+
if (rebuilt.code !== 0) {
|
|
23614
|
+
const reason2 = installFailureReason(rebuilt.stderr);
|
|
23615
|
+
throw new TrustError("trust.internal", reason2, [reason2]);
|
|
23616
|
+
}
|
|
23617
|
+
const reason = installFailureReason(refresh.stderr);
|
|
23618
|
+
throw new TrustError("trust.internal", reason, [reason]);
|
|
23376
23619
|
},
|
|
23377
23620
|
async caTrustRemover() {
|
|
23378
23621
|
try {
|
|
23379
|
-
unlinkSync2(
|
|
23622
|
+
unlinkSync2(DEBIAN_CERT);
|
|
23380
23623
|
} catch {
|
|
23381
23624
|
}
|
|
23625
|
+
if (!toolOnPath("update-ca-trust")) return;
|
|
23626
|
+
const present = P11_CERTS.filter((path2) => exists(path2));
|
|
23627
|
+
if (caBackend() !== "p11kit" && present.length === 0) return;
|
|
23628
|
+
for (const certPath of present) {
|
|
23629
|
+
await sudoOrThrow(["rm", "-f", certPath]);
|
|
23630
|
+
}
|
|
23631
|
+
await sudoOrThrow(["update-ca-trust"]);
|
|
23382
23632
|
},
|
|
23383
23633
|
async caTrustAnchorRemover(fingerprintSha1, certPem) {
|
|
23384
23634
|
void fingerprintSha1;
|
|
@@ -23545,13 +23795,15 @@ function createInstalledTrustController() {
|
|
|
23545
23795
|
const platform = process.platform;
|
|
23546
23796
|
const adapter = selectTrustPlatformAdapter(platform);
|
|
23547
23797
|
const installRoot = defaultTrustInstallRoot(platform);
|
|
23798
|
+
const manifestDirs = adapter.manifestDirs?.() ?? [];
|
|
23548
23799
|
return createRequestBodyTrustController({
|
|
23549
23800
|
platform,
|
|
23550
23801
|
installRoot,
|
|
23551
23802
|
hostPath: join5(installRoot, "runtime-host"),
|
|
23552
23803
|
hostName: "com.rogatio.runtime",
|
|
23553
23804
|
allowedOrigins: [],
|
|
23554
|
-
manifestDir: adapter.defaultManifestDir(),
|
|
23805
|
+
manifestDir: manifestDirs[0] ?? adapter.defaultManifestDir(),
|
|
23806
|
+
...manifestDirs.length > 0 ? { manifestDirs } : {},
|
|
23555
23807
|
detectCapabilities: () => adapter.detect(),
|
|
23556
23808
|
caTrustInstaller: (cert) => adapter.caTrustInstaller(cert),
|
|
23557
23809
|
caTrustRemover: () => adapter.caTrustRemover(),
|
|
@@ -33270,10 +33522,10 @@ function reportTrust(subcommand, result, okMessage) {
|
|
|
33270
33522
|
const reasons = result.reasons ?? ["unknown"];
|
|
33271
33523
|
console.error(`trust unsupported: ${reasons.join(", ")}`);
|
|
33272
33524
|
const hints = {
|
|
33273
|
-
"tooling-missing": "Hint: install required tooling (macOS: security; Linux: update-ca-certificates; Windows: certutil is built-in)",
|
|
33274
|
-
"manifest-dir-unwritable": "Hint: check permissions on
|
|
33525
|
+
"tooling-missing": "Hint: install required tooling (macOS: security; Linux: update-ca-certificates or update-ca-trust; Windows: certutil is built-in)",
|
|
33526
|
+
"manifest-dir-unwritable": "Hint: check permissions on the browser NativeMessagingHosts directory (Google Chrome or Chromium) or run with appropriate access",
|
|
33275
33527
|
"keychain-unwritable": "Hint: macOS login keychain not writable; try running with appropriate keychain access or use sudo for system keychain",
|
|
33276
|
-
"ca-store-unwritable": "Hint: /usr/local/share/ca-certificates
|
|
33528
|
+
"ca-store-unwritable": "Hint: the CA trust store is not writable, or this system has no supported anchors directory. Debian uses /usr/local/share/ca-certificates. Arch uses /etc/ca-certificates/trust-source/anchors. Fedora and RHEL use /etc/pki/ca-trust/source/anchors",
|
|
33277
33529
|
"elevation-required": "Hint: device-local CA trust requires root (Linux: sudo, macOS: keychain password, Windows: Administrator). Re-run with elevated privileges"
|
|
33278
33530
|
};
|
|
33279
33531
|
for (const reason of reasons) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rogatio/cli",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.17.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Local-first browser request and response rules — editor host, file verification, test runner, and runtime dispatch.",
|
|
@@ -20,9 +20,11 @@
|
|
|
20
20
|
"files": [
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
|
+
"main": "./dist/node/index.js",
|
|
24
|
+
"types": "./dist/node/index.d.ts",
|
|
23
25
|
"exports": {
|
|
24
26
|
".": {
|
|
25
|
-
"types": "./
|
|
27
|
+
"types": "./dist/node/index.d.ts",
|
|
26
28
|
"import": "./dist/node/index.js"
|
|
27
29
|
}
|
|
28
30
|
},
|