blun-king-cli 9.1.0 → 9.1.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/LIESMICH.txt +1 -1
- package/README.md +1 -1
- package/bin/blun.js +16 -2
- package/bin/core-bootstrap.js +6 -1
- package/bin/king.js +16 -2
- package/bin/launcher-mode.js +0 -0
- package/bin/launcher-runtime.js +1 -1
- package/bin/plugin-bootstrap.js +0 -0
- package/bin/private-paths.js +0 -0
- package/bin/update-lease.js +0 -0
- package/bin/update-notice.js +0 -0
- package/blun.mjs +58 -58
- package/package.json +1 -1
package/LIESMICH.txt
CHANGED
package/README.md
CHANGED
package/bin/blun.js
CHANGED
|
@@ -254,10 +254,24 @@ async function installLeaseIsClear() {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
async function main() {
|
|
257
|
+
const explicitUpdateRequest = process.argv.length === 3
|
|
258
|
+
&& /^(?:update|upgrade)$/iu.test(process.argv[2] || '');
|
|
257
259
|
const result = await acquireNoticeLease();
|
|
258
|
-
if (!result.acquired)
|
|
260
|
+
if (!result.acquired) {
|
|
261
|
+
process.stderr.write(explicitUpdateRequest
|
|
262
|
+
? 'BLUN laeuft noch. Beende die laufende Konsole und starte das Update erneut.\n'
|
|
263
|
+
: 'BLUN laeuft bereits in einer anderen Konsole.\n');
|
|
264
|
+
process.exitCode = 1;
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
259
267
|
try {
|
|
260
|
-
if (!await installLeaseIsClear())
|
|
268
|
+
if (!await installLeaseIsClear()) {
|
|
269
|
+
process.stderr.write(explicitUpdateRequest
|
|
270
|
+
? 'BLUN laeuft noch. Beende die laufende Konsole und starte das Update erneut.\n'
|
|
271
|
+
: 'BLUN laeuft bereits in einer anderen Konsole.\n');
|
|
272
|
+
process.exitCode = 1;
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
261
275
|
result.lease.assertOwned();
|
|
262
276
|
const { runLauncher } = require('./launcher-runtime');
|
|
263
277
|
result.lease.assertOwned();
|
package/bin/core-bootstrap.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const fs = require('node:fs');
|
|
3
4
|
const path = require('node:path');
|
|
4
5
|
const { pathToFileURL } = require('node:url');
|
|
5
6
|
|
|
@@ -41,7 +42,11 @@ async function runCoreBootstrap() {
|
|
|
41
42
|
|
|
42
43
|
if (require.main === module) {
|
|
43
44
|
// oxlint-disable-next-line unicorn/prefer-top-level-await -- Worker entry is CommonJS.
|
|
44
|
-
void runCoreBootstrap().catch(() =>
|
|
45
|
+
void runCoreBootstrap().catch((error) => {
|
|
46
|
+
const message = error && error.message ? error.message : String(error);
|
|
47
|
+
fs.writeSync(process.stderr.fd, `BLUN Start fehlgeschlagen: ${message}\n`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
});
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
module.exports = { CORE_LOADED_MESSAGE, runCoreBootstrap };
|
package/bin/king.js
CHANGED
|
@@ -254,10 +254,24 @@ async function installLeaseIsClear() {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
async function main() {
|
|
257
|
+
const explicitUpdateRequest = process.argv.length === 3
|
|
258
|
+
&& /^(?:update|upgrade)$/iu.test(process.argv[2] || '');
|
|
257
259
|
const result = await acquireNoticeLease();
|
|
258
|
-
if (!result.acquired)
|
|
260
|
+
if (!result.acquired) {
|
|
261
|
+
process.stderr.write(explicitUpdateRequest
|
|
262
|
+
? 'BLUN laeuft noch. Beende die laufende Konsole und starte das Update erneut.\n'
|
|
263
|
+
: 'BLUN laeuft bereits in einer anderen Konsole.\n');
|
|
264
|
+
process.exitCode = 1;
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
259
267
|
try {
|
|
260
|
-
if (!await installLeaseIsClear())
|
|
268
|
+
if (!await installLeaseIsClear()) {
|
|
269
|
+
process.stderr.write(explicitUpdateRequest
|
|
270
|
+
? 'BLUN laeuft noch. Beende die laufende Konsole und starte das Update erneut.\n'
|
|
271
|
+
: 'BLUN laeuft bereits in einer anderen Konsole.\n');
|
|
272
|
+
process.exitCode = 1;
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
261
275
|
result.lease.assertOwned();
|
|
262
276
|
const { runLauncher } = require('./launcher-runtime');
|
|
263
277
|
result.lease.assertOwned();
|
package/bin/launcher-mode.js
CHANGED
|
File without changes
|
package/bin/launcher-runtime.js
CHANGED
|
@@ -280,7 +280,7 @@ async function runLauncher(options = {}) {
|
|
|
280
280
|
env.BLUN_HOME = blunDir;
|
|
281
281
|
env.BLUN_MODEL_MAX_COMPLETION_TOKENS = env.BLUN_MODEL_MAX_COMPLETION_TOKENS || '32768';
|
|
282
282
|
process.exitCode = await superviseProtectedCore(
|
|
283
|
-
|
|
283
|
+
ARGS,
|
|
284
284
|
env,
|
|
285
285
|
callerCwd,
|
|
286
286
|
releaseNotice,
|
package/bin/plugin-bootstrap.js
CHANGED
|
File without changes
|
package/bin/private-paths.js
CHANGED
|
File without changes
|
package/bin/update-lease.js
CHANGED
|
File without changes
|
package/bin/update-notice.js
CHANGED
|
File without changes
|
package/blun.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:6d54e04788e3c465f647fe659f1ddd461d4e661c33aefaaea5550319c0d52dc1
|
|
3
3
|
import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
5
5
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
@@ -10433,6 +10433,38 @@ function parseAclFlags(flags) {
|
|
|
10433
10433
|
if (parsed.join("") !== flags) throw new Error("Malformed Windows ACL inheritance flags.");
|
|
10434
10434
|
return parsed.toSorted();
|
|
10435
10435
|
}
|
|
10436
|
+
function errorDetailAcl(error) {
|
|
10437
|
+
if (error !== null && typeof error === "object" && "stderr" in error) {
|
|
10438
|
+
const stderr = String(error.stderr ?? "").trim();
|
|
10439
|
+
if (stderr.length > 0) return stderr;
|
|
10440
|
+
}
|
|
10441
|
+
if (error instanceof Error && error.message.trim().length > 0) return error.message.trim();
|
|
10442
|
+
return String(error);
|
|
10443
|
+
}
|
|
10444
|
+
function unexpectedExplicitTrusteesAcl(savedAcl, userSid) {
|
|
10445
|
+
if (savedAcl.length === 0 || savedAcl.length % 2 !== 0) throw new Error("Windows ACL dump has an invalid UTF-16LE byte length.");
|
|
10446
|
+
const hasByteOrderMark = savedAcl[0] === 255 && savedAcl[1] === 254;
|
|
10447
|
+
const daclLines = savedAcl.subarray(hasByteOrderMark ? 2 : 0).toString("utf16le").split(/\r?\n/).filter((line) => line.startsWith("D:"));
|
|
10448
|
+
if (daclLines.length !== 1) throw new Error("Windows ACL dump does not contain exactly one DACL.");
|
|
10449
|
+
const dacl = daclLines[0];
|
|
10450
|
+
const firstAce = dacl.indexOf("(");
|
|
10451
|
+
if (firstAce === -1) return [];
|
|
10452
|
+
const aceText = dacl.slice(firstAce);
|
|
10453
|
+
const aceMatches = [...aceText.matchAll(/\(([^()]*)\)/g)];
|
|
10454
|
+
if (aceMatches.map((match) => match[0]).join("") !== aceText) throw new Error("Windows ACL dump contains malformed access rules.");
|
|
10455
|
+
const expectedTrustees = new Set([userSid.toUpperCase(), WINDOWS_SYSTEM_SID, WINDOWS_ADMINISTRATORS_SID]);
|
|
10456
|
+
const unexpected = new Set();
|
|
10457
|
+
for (const match of aceMatches) {
|
|
10458
|
+
const fields = match[1].split(";");
|
|
10459
|
+
if (fields.length < 6 || !fields[5]) throw new Error("Windows ACL dump contains a malformed access rule.");
|
|
10460
|
+
const flags = parseAclFlags(fields[1]);
|
|
10461
|
+
if (flags.includes("ID")) continue;
|
|
10462
|
+
const rawTrustee = fields[5].toUpperCase();
|
|
10463
|
+
const normalized = normalizeTrustee(rawTrustee);
|
|
10464
|
+
if (!expectedTrustees.has(normalized)) unexpected.add(rawTrustee);
|
|
10465
|
+
}
|
|
10466
|
+
return [...unexpected].toSorted();
|
|
10467
|
+
}
|
|
10436
10468
|
function assertExpectedDacl(savedAcl, userSid, kind) {
|
|
10437
10469
|
if (savedAcl.length === 0 || savedAcl.length % 2 !== 0) throw new Error("Windows ACL dump has an invalid UTF-16LE byte length.");
|
|
10438
10470
|
const hasByteOrderMark = savedAcl[0] === 255 && savedAcl[1] === 254;
|
|
@@ -10478,7 +10510,7 @@ var init_windows_private_acl = __esmMin((() => {
|
|
|
10478
10510
|
try {
|
|
10479
10511
|
this.apply(target, kind, userSid);
|
|
10480
10512
|
} catch (error) {
|
|
10481
|
-
throw new Error(
|
|
10513
|
+
throw new Error(`Windows credential ACL hardening failed: ${errorDetailAcl(error)}`, { cause: error });
|
|
10482
10514
|
}
|
|
10483
10515
|
this.verifyWithUserSid(target, kind, userSid);
|
|
10484
10516
|
}
|
|
@@ -10518,43 +10550,28 @@ var init_windows_private_acl = __esmMin((() => {
|
|
|
10518
10550
|
}
|
|
10519
10551
|
apply(target, kind, userSid) {
|
|
10520
10552
|
const absoluteTarget = resolve(target);
|
|
10521
|
-
|
|
10522
|
-
|
|
10553
|
+
if (basename(absoluteTarget).length === 0 || /[\r\n]/.test(absoluteTarget)) throw new Error("Windows credential ACL cannot target a volume root or newline path.");
|
|
10554
|
+
const unexpectedTrustees = unexpectedExplicitTrusteesAcl(this.save(absoluteTarget), userSid);
|
|
10555
|
+
const grant = kind === "directory" ? "(OI)(CI)F" : "F";
|
|
10556
|
+
this.runCommand(this.executable("icacls.exe"), [absoluteTarget, "/inheritance:r", "/Q"]);
|
|
10557
|
+
if (unexpectedTrustees.length > 0) this.runCommand(this.executable("icacls.exe"), [absoluteTarget, "/remove", ...unexpectedTrustees.map((trustee) => `*${trustee}`), "/Q"]);
|
|
10558
|
+
this.runCommand(this.executable("icacls.exe"), [absoluteTarget, "/remove:d", `*${userSid}`, `*${WINDOWS_SYSTEM_SID}`, `*${WINDOWS_ADMINISTRATORS_SID}`, "/Q"]);
|
|
10559
|
+
this.runCommand(this.executable("icacls.exe"), [absoluteTarget, "/grant:r", `*${userSid}:${grant}`, `*${WINDOWS_SYSTEM_SID}:${grant}`, `*${WINDOWS_ADMINISTRATORS_SID}:${grant}`, "/Q"]);
|
|
10560
|
+
}
|
|
10561
|
+
save(target) {
|
|
10523
10562
|
const aclFile = this.transferPath();
|
|
10524
|
-
const acl = `\uFEFF${targetName}\r\n${expectedDacl(userSid, kind)}\r\n`;
|
|
10525
|
-
let created = false;
|
|
10526
10563
|
try {
|
|
10527
|
-
|
|
10528
|
-
|
|
10529
|
-
flag: "wx",
|
|
10530
|
-
mode: 384
|
|
10531
|
-
});
|
|
10532
|
-
created = true;
|
|
10533
|
-
this.runCommand(this.executable("icacls.exe"), [
|
|
10534
|
-
dirname(absoluteTarget),
|
|
10535
|
-
"/restore",
|
|
10536
|
-
aclFile,
|
|
10537
|
-
"/Q"
|
|
10538
|
-
]);
|
|
10564
|
+
this.runCommand(this.executable("icacls.exe"), [target, "/save", aclFile, "/Q"]);
|
|
10565
|
+
return readFileSync(aclFile);
|
|
10539
10566
|
} finally {
|
|
10540
|
-
|
|
10567
|
+
this.removeTransferFile(aclFile);
|
|
10541
10568
|
}
|
|
10542
10569
|
}
|
|
10543
10570
|
verifyWithUserSid(target, kind, userSid) {
|
|
10544
|
-
const absoluteTarget = resolve(target);
|
|
10545
|
-
const aclFile = this.transferPath();
|
|
10546
10571
|
try {
|
|
10547
|
-
|
|
10548
|
-
absoluteTarget,
|
|
10549
|
-
"/save",
|
|
10550
|
-
aclFile,
|
|
10551
|
-
"/Q"
|
|
10552
|
-
]);
|
|
10553
|
-
assertExpectedDacl(readFileSync(aclFile), userSid, kind);
|
|
10572
|
+
assertExpectedDacl(this.save(resolve(target)), userSid, kind);
|
|
10554
10573
|
} catch (error) {
|
|
10555
|
-
throw new Error(
|
|
10556
|
-
} finally {
|
|
10557
|
-
this.removeTransferFile(aclFile);
|
|
10574
|
+
throw new Error(`Windows credential ACL verification failed: ${errorDetailAcl(error)}`, { cause: error });
|
|
10558
10575
|
}
|
|
10559
10576
|
}
|
|
10560
10577
|
};
|
|
@@ -499190,29 +499207,9 @@ function renderQuotaSegment(window, colors, options) {
|
|
|
499190
499207
|
const reset = options.includeReset ? formatQuotaReset(window.resetAt, options.locale, options.timeZone) : "";
|
|
499191
499208
|
return `${label} ${bar} ${percentage}${chalk.hex(colors.textDim)(reset)}`;
|
|
499192
499209
|
}
|
|
499193
|
-
function
|
|
499194
|
-
const
|
|
499195
|
-
|
|
499196
|
-
for (const segment of segments) {
|
|
499197
|
-
if (current.length === 0) {
|
|
499198
|
-
current = segment;
|
|
499199
|
-
continue;
|
|
499200
|
-
}
|
|
499201
|
-
const joined = `${current}${QUOTA_SEGMENT_GAP}${segment}`;
|
|
499202
|
-
if (visibleWidth(joined) <= width) current = joined;
|
|
499203
|
-
else {
|
|
499204
|
-
lines.push(current);
|
|
499205
|
-
current = segment;
|
|
499206
|
-
}
|
|
499207
|
-
}
|
|
499208
|
-
if (current.length > 0) lines.push(current);
|
|
499209
|
-
return lines;
|
|
499210
|
-
}
|
|
499211
|
-
function centerQuotaLines(lines, width) {
|
|
499212
|
-
return lines.map((line) => {
|
|
499213
|
-
const leftPadding = Math.max(0, Math.floor((width - visibleWidth(line)) / 2));
|
|
499214
|
-
return `${" ".repeat(leftPadding)}${line}`;
|
|
499215
|
-
});
|
|
499210
|
+
function centerQuotaLine(line, width) {
|
|
499211
|
+
const leftPadding = Math.max(0, Math.floor((width - visibleWidth(line)) / 2));
|
|
499212
|
+
return `${" ".repeat(leftPadding)}${line}`;
|
|
499216
499213
|
}
|
|
499217
499214
|
function formatManagedQuotaFooterLines(windows, colors, width, options = {}) {
|
|
499218
499215
|
if (windows.length === 0 || width <= 0) return [];
|
|
@@ -499236,14 +499233,17 @@ function formatManagedQuotaFooterLines(windows, colors, width, options = {}) {
|
|
|
499236
499233
|
}
|
|
499237
499234
|
];
|
|
499238
499235
|
for (const variant of variants) {
|
|
499239
|
-
const
|
|
499236
|
+
const line = windows.map((window) => renderQuotaSegment(window, colors, {
|
|
499240
499237
|
...variant,
|
|
499241
499238
|
locale,
|
|
499242
499239
|
timeZone: options.timeZone
|
|
499243
|
-
}));
|
|
499244
|
-
if (
|
|
499240
|
+
})).join(QUOTA_SEGMENT_GAP);
|
|
499241
|
+
if (visibleWidth(line) <= width) return [centerQuotaLine(line, width)];
|
|
499245
499242
|
}
|
|
499246
|
-
return
|
|
499243
|
+
return [centerQuotaLine(truncateToWidth(windows.map((window) => {
|
|
499244
|
+
const percentage = window.unlimited === true ? "∞" : `${String(Math.round(window.fraction * 100))}%`;
|
|
499245
|
+
return `${quotaWindowLabel(window.id)} ${percentage}`;
|
|
499246
|
+
}).join(" · "), width, "…"), width)];
|
|
499247
499247
|
}
|
|
499248
499248
|
function renderContextBar(ratio, colors) {
|
|
499249
499249
|
const clamped = Math.max(0, Math.min(1, ratio));
|