@dotobokuri/fleet-console 1.71.1 → 1.72.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/CLAUDE.md +1 -1
- package/README.md +13 -0
- package/dist/cli.mjs +396 -339
- package/dist/client/assets/{_baseUniq-Bhd1wyKE.js → _baseUniq-D_AjNlwO.js} +1 -1
- package/dist/client/assets/{arc-Cu9FOmUr.js → arc-DiscagS3.js} +1 -1
- package/dist/client/assets/{architectureDiagram-Q4EWVU46-Dq9FA5I3.js → architectureDiagram-Q4EWVU46-PGPwULb9.js} +1 -1
- package/dist/client/assets/{blockDiagram-DXYQGD6D-BDZkCLI1.js → blockDiagram-DXYQGD6D-DLexJaxZ.js} +1 -1
- package/dist/client/assets/{c4Diagram-AHTNJAMY-XBPYwanu.js → c4Diagram-AHTNJAMY-D9Ye73ny.js} +1 -1
- package/dist/client/assets/channel-CR5OWwKU.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-BbTQSLs0.js → chunk-4BX2VUAB-B7YgJYL4.js} +1 -1
- package/dist/client/assets/{chunk-4TB4RGXK-DukpmkUz.js → chunk-4TB4RGXK-CEEQcTWi.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-BFyIa1Ge.js → chunk-55IACEB6-B8AcnGT7.js} +1 -1
- package/dist/client/assets/{chunk-EDXVE4YY-D7RHsfQm.js → chunk-EDXVE4YY-DjZ88S2h.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-Co64dt-k.js → chunk-FMBD7UC4-io3C2TDz.js} +1 -1
- package/dist/client/assets/{chunk-OYMX7WX6-CdycD6Yh.js → chunk-OYMX7WX6-s0DPD-0B.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-CNvTB1xu.js → chunk-QZHKN3VN-DGcrSXIn.js} +1 -1
- package/dist/client/assets/{chunk-YZCP3GAM-CY1_pTO2.js → chunk-YZCP3GAM-Dp1DewA_.js} +1 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-BxfrF-vv.js +1 -0
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-BxfrF-vv.js +1 -0
- package/dist/client/assets/clone-BH8tX1wM.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-PLhfHDPQ.js → cose-bilkent-S5V4N54A-D9PZkL8M.js} +1 -1
- package/dist/client/assets/{dagre-KV5264BT-gJnGByq0.js → dagre-KV5264BT-M-8Bl0QN.js} +1 -1
- package/dist/client/assets/{diagram-5BDNPKRD-y48OdlFp.js → diagram-5BDNPKRD-CbFVI18N.js} +1 -1
- package/dist/client/assets/{diagram-G4DWMVQ6-DSLYc2V1.js → diagram-G4DWMVQ6-Bofydoge.js} +1 -1
- package/dist/client/assets/{diagram-MMDJMWI5-DWgtcwcn.js → diagram-MMDJMWI5-BZQV1jqh.js} +1 -1
- package/dist/client/assets/{diagram-TYMM5635-CLd83m-G.js → diagram-TYMM5635-v_pX67fP.js} +1 -1
- package/dist/client/assets/{erDiagram-SMLLAGMA-CGP2g7Ug.js → erDiagram-SMLLAGMA-DA8k24I7.js} +1 -1
- package/dist/client/assets/{flowDiagram-DWJPFMVM-BhKzXbma.js → flowDiagram-DWJPFMVM-CA3Jm5mj.js} +1 -1
- package/dist/client/assets/{ganttDiagram-T4ZO3ILL-BdpBmhZF.js → ganttDiagram-T4ZO3ILL-B6YPlixu.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-IylczS5r.js → gitGraphDiagram-UUTBAWPF-3BjoRhTq.js} +1 -1
- package/dist/client/assets/{graph-xlKIIKKy.js → graph-CjQR1bpo.js} +1 -1
- package/dist/client/assets/{index-DH7xHFza.js → index-B21kBRWF.js} +70 -70
- package/dist/client/assets/{infoDiagram-42DDH7IO-Dm9-Iqxb.js → infoDiagram-42DDH7IO-Cz8NXcwy.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-0tPrKKU3.js → ishikawaDiagram-UXIWVN3A-dJiEc4oW.js} +1 -1
- package/dist/client/assets/{journeyDiagram-VCZTEJTY-3wTioYxO.js → journeyDiagram-VCZTEJTY-D0e9gSNl.js} +1 -1
- package/dist/client/assets/{kanban-definition-6JOO6SKY-DjVcpuse.js → kanban-definition-6JOO6SKY-DJ-tyN1D.js} +1 -1
- package/dist/client/assets/{layout-BZ0nnXEn.js → layout-By8oq65c.js} +1 -1
- package/dist/client/assets/{linear-DNdW4gLV.js → linear-Bgvt1y1F.js} +1 -1
- package/dist/client/assets/{mermaid.core-DpO6yFcA.js → mermaid.core-BzUsxrJd.js} +4 -4
- package/dist/client/assets/{min-xMtTJxkM.js → min-C5LKMAsm.js} +1 -1
- package/dist/client/assets/{mindmap-definition-QFDTVHPH-8tcRIKM5.js → mindmap-definition-QFDTVHPH-BVEgUjPO.js} +1 -1
- package/dist/client/assets/{pieDiagram-DEJITSTG-DOuWZGrv.js → pieDiagram-DEJITSTG-H6ERErU1.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-34T5L4WZ-BWPtgVdA.js → quadrantDiagram-34T5L4WZ-B3Y2XYCJ.js} +1 -1
- package/dist/client/assets/{requirementDiagram-MS252O5E-CkNpSYqR.js → requirementDiagram-MS252O5E-NgcHrVQM.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-XADWPNL6-DUPS39lN.js → sankeyDiagram-XADWPNL6-DtmwsCxU.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-FGHM5R23-B4n7l5jw.js → sequenceDiagram-FGHM5R23-Rd0S2w1n.js} +1 -1
- package/dist/client/assets/{stateDiagram-FHFEXIEX-DBHsG7yj.js → stateDiagram-FHFEXIEX-Cpag_fk7.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-Cbjujcp-.js +1 -0
- package/dist/client/assets/{timeline-definition-GMOUNBTQ-BLxUyg3R.js → timeline-definition-GMOUNBTQ-C8yS2XLP.js} +1 -1
- package/dist/client/assets/{vennDiagram-DHZGUBPP-27NkxCen.js → vennDiagram-DHZGUBPP-Bj7SvZFm.js} +1 -1
- package/dist/client/assets/{wardley-RL74JXVD-VNgEaZlH.js → wardley-RL74JXVD-DZhhw2v9.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-NUSXRM2D-byIhDvPD.js → wardleyDiagram-NUSXRM2D-DgpBbIN3.js} +1 -1
- package/dist/client/assets/{xychartDiagram-5P7HB3ND-D0amCilL.js → xychartDiagram-5P7HB3ND-CUq82Sal.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/fleet-plugins/ledger/routes.mjs +62 -5
- package/dist/fleet-plugins/quota/routes.mjs +621 -137
- package/dist/fleet-plugins/scuttlebutt/routes.mjs +62 -5
- package/dist/fleet-plugins/terminal/routes.mjs +1521 -502
- package/dist/fleet.mjs +2885 -633
- package/package.json +1 -1
- package/dist/client/assets/channel-BTX-SvBb.js +0 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-CixB9uB6.js +0 -1
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-CixB9uB6.js +0 -1
- package/dist/client/assets/clone-DuMuKBBB.js +0 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2--18aeGq2.js +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
2
|
+
import * as fs10 from 'node:fs';
|
|
3
|
+
import fs10__default, { realpathSync, accessSync, constants as constants$1, existsSync, lstatSync } from 'node:fs';
|
|
4
4
|
import * as path18 from 'node:path';
|
|
5
5
|
import path18__default, { join, resolve, relative, sep } from 'node:path';
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
@@ -14,7 +14,8 @@ import http from 'node:http';
|
|
|
14
14
|
import https from 'node:https';
|
|
15
15
|
import { mkdtemp, rm, mkdir, readdir, readFile, stat, appendFile, writeFile, rename, realpath, lstat } from 'node:fs/promises';
|
|
16
16
|
import fontList from 'font-list';
|
|
17
|
-
import
|
|
17
|
+
import net3 from 'node:net';
|
|
18
|
+
import tls from 'node:tls';
|
|
18
19
|
import { execFile } from 'child_process';
|
|
19
20
|
import { constants } from 'fs';
|
|
20
21
|
import 'fs/promises';
|
|
@@ -24,7 +25,6 @@ import { deflateRawSync } from 'zlib';
|
|
|
24
25
|
import { EventEmitter } from 'node:events';
|
|
25
26
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
26
27
|
import selfsigned from 'selfsigned';
|
|
27
|
-
import tls from 'node:tls';
|
|
28
28
|
|
|
29
29
|
var __defProp = Object.defineProperty;
|
|
30
30
|
var __export = (target, all) => {
|
|
@@ -238,6 +238,18 @@ function createConsoleHealthClient(deps = {}) {
|
|
|
238
238
|
}
|
|
239
239
|
return { probe };
|
|
240
240
|
}
|
|
241
|
+
function createConsoleStalePolicy(deps = {}) {
|
|
242
|
+
const fsImpl = deps.fs ?? fs10__default;
|
|
243
|
+
function isBuildStale(lock, buildFile) {
|
|
244
|
+
try {
|
|
245
|
+
return lock.startedAt < fsImpl.statSync(buildFile).mtimeMs;
|
|
246
|
+
} catch (err) {
|
|
247
|
+
if (err.code === "ENOENT") return false;
|
|
248
|
+
throw err;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return { isBuildStale };
|
|
252
|
+
}
|
|
241
253
|
|
|
242
254
|
// cli/styles/tokens.ts
|
|
243
255
|
var ANSI_RESET = "\x1B[0m";
|
|
@@ -301,7 +313,7 @@ function readFleetCliRelease() {
|
|
|
301
313
|
var LOCK_DIR_MODE = 448;
|
|
302
314
|
var LOCK_FILE_MODE = 384;
|
|
303
315
|
function createConsoleLock(deps = {}) {
|
|
304
|
-
const fsImpl = deps.fs ??
|
|
316
|
+
const fsImpl = deps.fs ?? fs10__default;
|
|
305
317
|
const now = deps.now ?? Date.now;
|
|
306
318
|
const randomToken = deps.randomToken ?? (() => crypto5.randomBytes(32).toString("base64url"));
|
|
307
319
|
const hostname5 = deps.hostname ?? (() => "127.0.0.1");
|
|
@@ -333,7 +345,7 @@ function createConsoleLock(deps = {}) {
|
|
|
333
345
|
version: input.version,
|
|
334
346
|
...input.owner ? { owner: input.owner } : {}
|
|
335
347
|
};
|
|
336
|
-
const fd = fsImpl.openSync(input.lockFile,
|
|
348
|
+
const fd = fsImpl.openSync(input.lockFile, fs10__default.constants.O_CREAT | fs10__default.constants.O_EXCL | fs10__default.constants.O_WRONLY, LOCK_FILE_MODE);
|
|
337
349
|
try {
|
|
338
350
|
fsImpl.writeFileSync(fd, `${JSON.stringify(payload, null, 2)}
|
|
339
351
|
`, "utf8");
|
|
@@ -409,10 +421,10 @@ function getFleetDataDir(env = process.env) {
|
|
|
409
421
|
}
|
|
410
422
|
var SECURE_DIR_MODE = 448;
|
|
411
423
|
var SECURE_FILE_MODE = 384;
|
|
412
|
-
var NOFOLLOW_FLAG =
|
|
424
|
+
var NOFOLLOW_FLAG = fs10.constants.O_NOFOLLOW ?? 0;
|
|
413
425
|
function safeLstat(targetPath) {
|
|
414
426
|
try {
|
|
415
|
-
return
|
|
427
|
+
return fs10.lstatSync(targetPath);
|
|
416
428
|
} catch (error51) {
|
|
417
429
|
if (error51.code === "ENOENT") {
|
|
418
430
|
return null;
|
|
@@ -426,15 +438,15 @@ function ensureSafeDirectory(dirPath) {
|
|
|
426
438
|
if (!stat4.isDirectory() || stat4.isSymbolicLink()) {
|
|
427
439
|
throw new Error(`Unsafe Fleet directory: ${dirPath}`);
|
|
428
440
|
}
|
|
429
|
-
|
|
441
|
+
fs10.chmodSync(dirPath, SECURE_DIR_MODE);
|
|
430
442
|
return;
|
|
431
443
|
}
|
|
432
|
-
|
|
444
|
+
fs10.mkdirSync(dirPath, { recursive: true, mode: SECURE_DIR_MODE });
|
|
433
445
|
const created = safeLstat(dirPath);
|
|
434
446
|
if (!created?.isDirectory() || created.isSymbolicLink()) {
|
|
435
447
|
throw new Error(`Unsafe Fleet directory: ${dirPath}`);
|
|
436
448
|
}
|
|
437
|
-
|
|
449
|
+
fs10.chmodSync(dirPath, SECURE_DIR_MODE);
|
|
438
450
|
}
|
|
439
451
|
function assertWithinRoot(root, candidatePath) {
|
|
440
452
|
const resolvedRoot = path18.resolve(root);
|
|
@@ -460,17 +472,17 @@ function writeAtomicSync(filePath, content, options = {}) {
|
|
|
460
472
|
const tempPath = buildTempPath(filePath);
|
|
461
473
|
let tempCreated = false;
|
|
462
474
|
try {
|
|
463
|
-
|
|
475
|
+
fs10.writeFileSync(tempPath, content, { encoding: "utf-8", flag: "wx", mode });
|
|
464
476
|
tempCreated = true;
|
|
465
477
|
if (doFsync) {
|
|
466
|
-
const fd =
|
|
478
|
+
const fd = fs10.openSync(tempPath, "r");
|
|
467
479
|
try {
|
|
468
480
|
fsyncSyncBestEffort(fd);
|
|
469
481
|
} finally {
|
|
470
|
-
|
|
482
|
+
fs10.closeSync(fd);
|
|
471
483
|
}
|
|
472
484
|
}
|
|
473
|
-
|
|
485
|
+
fs10.renameSync(tempPath, filePath);
|
|
474
486
|
return;
|
|
475
487
|
} catch (error51) {
|
|
476
488
|
const code = error51.code;
|
|
@@ -480,7 +492,7 @@ function writeAtomicSync(filePath, content, options = {}) {
|
|
|
480
492
|
}
|
|
481
493
|
if (tempCreated) {
|
|
482
494
|
try {
|
|
483
|
-
|
|
495
|
+
fs10.unlinkSync(tempPath);
|
|
484
496
|
} catch {
|
|
485
497
|
}
|
|
486
498
|
}
|
|
@@ -492,7 +504,7 @@ function writeAtomicSync(filePath, content, options = {}) {
|
|
|
492
504
|
function cleanupTempFiles(dir, prefix, minAgeMs, now) {
|
|
493
505
|
let entries;
|
|
494
506
|
try {
|
|
495
|
-
entries =
|
|
507
|
+
entries = fs10.readdirSync(dir);
|
|
496
508
|
} catch {
|
|
497
509
|
return;
|
|
498
510
|
}
|
|
@@ -502,9 +514,9 @@ function cleanupTempFiles(dir, prefix, minAgeMs, now) {
|
|
|
502
514
|
}
|
|
503
515
|
const tempPath = path18.join(dir, entry);
|
|
504
516
|
try {
|
|
505
|
-
const stat4 =
|
|
517
|
+
const stat4 = fs10.lstatSync(tempPath);
|
|
506
518
|
if (stat4?.isFile() && !stat4.isSymbolicLink() && now - stat4.mtimeMs >= minAgeMs) {
|
|
507
|
-
|
|
519
|
+
fs10.unlinkSync(tempPath);
|
|
508
520
|
}
|
|
509
521
|
} catch {
|
|
510
522
|
}
|
|
@@ -516,7 +528,7 @@ function isIgnoredFsyncError(error51) {
|
|
|
516
528
|
}
|
|
517
529
|
function fsyncSyncBestEffort(fd) {
|
|
518
530
|
try {
|
|
519
|
-
|
|
531
|
+
fs10.fsyncSync(fd);
|
|
520
532
|
} catch (error51) {
|
|
521
533
|
if (!isIgnoredFsyncError(error51)) {
|
|
522
534
|
throw error51;
|
|
@@ -536,7 +548,7 @@ function withDirectoryLock(deps, operation) {
|
|
|
536
548
|
const startedAt = now();
|
|
537
549
|
while (true) {
|
|
538
550
|
try {
|
|
539
|
-
|
|
551
|
+
fs10.mkdirSync(deps.lockDir, { mode: 448 });
|
|
540
552
|
writeLockOwner(deps.lockDir, ownerFileName, now());
|
|
541
553
|
try {
|
|
542
554
|
return operation();
|
|
@@ -556,7 +568,7 @@ function withDirectoryLock(deps, operation) {
|
|
|
556
568
|
}
|
|
557
569
|
function releaseLock(lockDir) {
|
|
558
570
|
try {
|
|
559
|
-
|
|
571
|
+
fs10.rmSync(lockDir, { recursive: true, force: true });
|
|
560
572
|
} catch {
|
|
561
573
|
}
|
|
562
574
|
}
|
|
@@ -566,14 +578,14 @@ function recoverStaleLock(lockDir, ownerFileName, now, staleLockMs) {
|
|
|
566
578
|
if (!isRecoverableSnapshot(initialSnapshot, now, staleLockMs)) return;
|
|
567
579
|
const quarantineDir = buildQuarantinePath(lockDir);
|
|
568
580
|
try {
|
|
569
|
-
|
|
581
|
+
fs10.renameSync(lockDir, quarantineDir);
|
|
570
582
|
} catch {
|
|
571
583
|
return;
|
|
572
584
|
}
|
|
573
585
|
try {
|
|
574
586
|
const quarantinedSnapshot = readLockSnapshot(quarantineDir, ownerFileName);
|
|
575
587
|
if (sameLockSnapshot(initialSnapshot, quarantinedSnapshot) && isRecoverableSnapshot(quarantinedSnapshot, now, staleLockMs)) {
|
|
576
|
-
|
|
588
|
+
fs10.rmSync(quarantineDir, { recursive: true, force: true });
|
|
577
589
|
} else {
|
|
578
590
|
restoreQuarantinedLock(quarantineDir, lockDir);
|
|
579
591
|
}
|
|
@@ -587,7 +599,7 @@ function recoverStaleLock(lockDir, ownerFileName, now, staleLockMs) {
|
|
|
587
599
|
}
|
|
588
600
|
}
|
|
589
601
|
function readLockSnapshot(lockDir, ownerFileName) {
|
|
590
|
-
const stat4 =
|
|
602
|
+
const stat4 = fs10.lstatSync(lockDir);
|
|
591
603
|
if (stat4.isSymbolicLink()) {
|
|
592
604
|
return { owner: null, mtimeMs: 0 };
|
|
593
605
|
}
|
|
@@ -608,7 +620,7 @@ function writeLockOwner(lockDir, ownerFileName, startedAt) {
|
|
|
608
620
|
};
|
|
609
621
|
const ownerPath = path18.join(lockDir, ownerFileName);
|
|
610
622
|
try {
|
|
611
|
-
|
|
623
|
+
fs10.writeFileSync(ownerPath, JSON.stringify(owner), { encoding: "utf-8", mode: 384 });
|
|
612
624
|
} catch (error51) {
|
|
613
625
|
releaseLock(lockDir);
|
|
614
626
|
throw error51;
|
|
@@ -617,7 +629,7 @@ function writeLockOwner(lockDir, ownerFileName, startedAt) {
|
|
|
617
629
|
function readLockOwner(lockDir, ownerFileName) {
|
|
618
630
|
const ownerPath = path18.join(lockDir, ownerFileName);
|
|
619
631
|
try {
|
|
620
|
-
return sanitizeLockOwner(JSON.parse(
|
|
632
|
+
return sanitizeLockOwner(JSON.parse(fs10.readFileSync(ownerPath, "utf-8")));
|
|
621
633
|
} catch (error51) {
|
|
622
634
|
const code = error51.code;
|
|
623
635
|
if (code === "ENOENT") return null;
|
|
@@ -639,7 +651,7 @@ function sameLockSnapshot(a, b) {
|
|
|
639
651
|
}
|
|
640
652
|
function restoreQuarantinedLock(quarantineDir, lockDir) {
|
|
641
653
|
try {
|
|
642
|
-
|
|
654
|
+
fs10.renameSync(quarantineDir, lockDir);
|
|
643
655
|
} catch {
|
|
644
656
|
}
|
|
645
657
|
}
|
|
@@ -679,17 +691,17 @@ var AUTH_LOCK_TIMEOUT_MS = 5e3;
|
|
|
679
691
|
function readAuthStoreFile(filePath) {
|
|
680
692
|
let fd;
|
|
681
693
|
try {
|
|
682
|
-
fd =
|
|
683
|
-
if (!
|
|
694
|
+
fd = fs10.openSync(filePath, fs10.constants.O_RDONLY | NOFOLLOW_FLAG);
|
|
695
|
+
if (!fs10.fstatSync(fd).isFile()) {
|
|
684
696
|
return {};
|
|
685
697
|
}
|
|
686
|
-
return JSON.parse(
|
|
698
|
+
return JSON.parse(fs10.readFileSync(fd, "utf-8"));
|
|
687
699
|
} catch {
|
|
688
700
|
return {};
|
|
689
701
|
} finally {
|
|
690
702
|
if (fd !== void 0) {
|
|
691
703
|
try {
|
|
692
|
-
|
|
704
|
+
fs10.closeSync(fd);
|
|
693
705
|
} catch {
|
|
694
706
|
}
|
|
695
707
|
}
|
|
@@ -703,7 +715,7 @@ function createAuthService(deps = {}) {
|
|
|
703
715
|
async deleteApiKey(providerId) {
|
|
704
716
|
let deleted = false;
|
|
705
717
|
withAuthLock(authPath, lockDir, () => {
|
|
706
|
-
if (!
|
|
718
|
+
if (!fs10.existsSync(authPath)) return;
|
|
707
719
|
const data = readAuthStoreFile(authPath);
|
|
708
720
|
if (!Object.prototype.hasOwnProperty.call(data, providerId)) return;
|
|
709
721
|
delete data[providerId];
|
|
@@ -716,21 +728,21 @@ function createAuthService(deps = {}) {
|
|
|
716
728
|
async getApiKey(providerId) {
|
|
717
729
|
let fd;
|
|
718
730
|
try {
|
|
719
|
-
if (!
|
|
731
|
+
if (!fs10.existsSync(authPath)) {
|
|
720
732
|
return void 0;
|
|
721
733
|
}
|
|
722
|
-
fd =
|
|
723
|
-
if (!
|
|
734
|
+
fd = fs10.openSync(authPath, fs10.constants.O_RDONLY | NOFOLLOW_FLAG);
|
|
735
|
+
if (!fs10.fstatSync(fd).isFile()) {
|
|
724
736
|
return void 0;
|
|
725
737
|
}
|
|
726
|
-
const data = JSON.parse(
|
|
738
|
+
const data = JSON.parse(fs10.readFileSync(fd, "utf-8"));
|
|
727
739
|
return typeof data[providerId]?.key === "string" ? data[providerId].key : void 0;
|
|
728
740
|
} catch {
|
|
729
741
|
return void 0;
|
|
730
742
|
} finally {
|
|
731
743
|
if (fd !== void 0) {
|
|
732
744
|
try {
|
|
733
|
-
|
|
745
|
+
fs10.closeSync(fd);
|
|
734
746
|
} catch {
|
|
735
747
|
}
|
|
736
748
|
}
|
|
@@ -738,7 +750,7 @@ function createAuthService(deps = {}) {
|
|
|
738
750
|
},
|
|
739
751
|
// [HIGH #2] 읽기 경로: fd 기반 O_RDONLY|O_NOFOLLOW 통일
|
|
740
752
|
async listProviderIds() {
|
|
741
|
-
if (!
|
|
753
|
+
if (!fs10.existsSync(authPath)) {
|
|
742
754
|
return [];
|
|
743
755
|
}
|
|
744
756
|
try {
|
|
@@ -751,7 +763,7 @@ function createAuthService(deps = {}) {
|
|
|
751
763
|
const dir = path18.dirname(authPath);
|
|
752
764
|
ensureSafeDirectory(dir);
|
|
753
765
|
withAuthLock(authPath, lockDir, () => {
|
|
754
|
-
const data =
|
|
766
|
+
const data = fs10.existsSync(authPath) ? readAuthStoreFile(authPath) : {};
|
|
755
767
|
data[providerId] = {
|
|
756
768
|
...data[providerId] ?? {},
|
|
757
769
|
key
|
|
@@ -834,21 +846,21 @@ function createDurableJsonStore(deps) {
|
|
|
834
846
|
function readJsonFile(filePath, sanitize) {
|
|
835
847
|
let fd;
|
|
836
848
|
try {
|
|
837
|
-
const stat4 =
|
|
849
|
+
const stat4 = fs10.lstatSync(filePath);
|
|
838
850
|
if (!stat4 || !stat4.isFile() || stat4.isSymbolicLink()) {
|
|
839
851
|
return sanitize(void 0);
|
|
840
852
|
}
|
|
841
|
-
fd =
|
|
842
|
-
if (!
|
|
853
|
+
fd = fs10.openSync(filePath, fs10.constants.O_RDONLY | NOFOLLOW_FLAG);
|
|
854
|
+
if (!fs10.fstatSync(fd).isFile()) {
|
|
843
855
|
return sanitize(void 0);
|
|
844
856
|
}
|
|
845
|
-
return sanitize(JSON.parse(
|
|
857
|
+
return sanitize(JSON.parse(fs10.readFileSync(fd, "utf-8")));
|
|
846
858
|
} catch {
|
|
847
859
|
return sanitize(void 0);
|
|
848
860
|
} finally {
|
|
849
861
|
if (fd !== void 0) {
|
|
850
862
|
try {
|
|
851
|
-
|
|
863
|
+
fs10.closeSync(fd);
|
|
852
864
|
} catch {
|
|
853
865
|
}
|
|
854
866
|
}
|
|
@@ -858,7 +870,7 @@ function ensureSafeDirectoryIfSensitive(dir, sensitivity) {
|
|
|
858
870
|
if (sensitivity === "sensitive") {
|
|
859
871
|
ensureSafeDirectory(dir);
|
|
860
872
|
} else {
|
|
861
|
-
|
|
873
|
+
fs10.mkdirSync(dir, { recursive: true });
|
|
862
874
|
}
|
|
863
875
|
}
|
|
864
876
|
|
|
@@ -998,7 +1010,7 @@ function canonicalizeWorkspaceCwd(cwd) {
|
|
|
998
1010
|
if (!cwd.trim()) {
|
|
999
1011
|
throw new Error("Workspace cwd is required");
|
|
1000
1012
|
}
|
|
1001
|
-
return
|
|
1013
|
+
return fs10.realpathSync.native(path18.resolve(cwd));
|
|
1002
1014
|
}
|
|
1003
1015
|
function assertWorkspaceDirectoryName(name) {
|
|
1004
1016
|
if (!name || !WORKSPACE_NAME_PATTERN.test(name)) {
|
|
@@ -1013,7 +1025,7 @@ function readWorkspaceIdentity(identityPath) {
|
|
|
1013
1025
|
}
|
|
1014
1026
|
let parsed;
|
|
1015
1027
|
try {
|
|
1016
|
-
parsed = JSON.parse(
|
|
1028
|
+
parsed = JSON.parse(fs10.readFileSync(identityPath, "utf8"));
|
|
1017
1029
|
} catch (error51) {
|
|
1018
1030
|
throw new Error(`Invalid workspace identity file: ${identityPath}`, { cause: error51 });
|
|
1019
1031
|
}
|
|
@@ -1100,11 +1112,11 @@ function isDesktopDevelopmentEnvironment2(env = process.env) {
|
|
|
1100
1112
|
}
|
|
1101
1113
|
function validateDesktopResourceRoot(root, expectedPackageRoot = resolveDesktopProtocolPackageRoot()) {
|
|
1102
1114
|
if (!path18__default.isAbsolute(root)) throw new Error("desktop_resource_root_not_absolute");
|
|
1103
|
-
const resolvedRoot =
|
|
1104
|
-
const expectedRoot =
|
|
1115
|
+
const resolvedRoot = fs10__default.realpathSync(root);
|
|
1116
|
+
const expectedRoot = fs10__default.realpathSync(expectedPackageRoot);
|
|
1105
1117
|
if (resolvedRoot !== expectedRoot) throw new Error("desktop_resource_root_invalid");
|
|
1106
1118
|
const markerPath = path18__default.join(resolvedRoot, DESKTOP_RESOURCE_ROOT_MARKER);
|
|
1107
|
-
const marker =
|
|
1119
|
+
const marker = fs10__default.readFileSync(markerPath, "utf8");
|
|
1108
1120
|
if (!isDesktopResourceRootMarkerValid(marker)) throw new Error("desktop_resource_root_marker_invalid");
|
|
1109
1121
|
return resolvedRoot;
|
|
1110
1122
|
}
|
|
@@ -1112,11 +1124,11 @@ function validateDesktopDevelopmentResourceRoot(root) {
|
|
|
1112
1124
|
if (!path18__default.isAbsolute(root)) throw new Error("desktop_resource_root_not_absolute");
|
|
1113
1125
|
let resolvedRoot;
|
|
1114
1126
|
try {
|
|
1115
|
-
resolvedRoot =
|
|
1127
|
+
resolvedRoot = fs10__default.realpathSync(root);
|
|
1116
1128
|
} catch {
|
|
1117
1129
|
throw new Error("desktop_development_resource_root_invalid");
|
|
1118
1130
|
}
|
|
1119
|
-
const expectedRoot =
|
|
1131
|
+
const expectedRoot = fs10__default.realpathSync(resolveDesktopProtocolPackageRoot());
|
|
1120
1132
|
if (resolvedRoot !== expectedRoot) throw new Error("desktop_development_resource_root_invalid");
|
|
1121
1133
|
return resolvedRoot;
|
|
1122
1134
|
}
|
|
@@ -11738,7 +11750,7 @@ function resolveLocked(workspace, hooks) {
|
|
|
11738
11750
|
const stagingState = inspectTree(staging2);
|
|
11739
11751
|
if (stagingState === "content") {
|
|
11740
11752
|
removeEmptyDirectories(destination);
|
|
11741
|
-
|
|
11753
|
+
fs10.renameSync(staging2, destination);
|
|
11742
11754
|
syncDirectory(workspace.path);
|
|
11743
11755
|
} else if (stagingState !== "missing") throw new Error("Unsafe Fleet Wiki migration staging state");
|
|
11744
11756
|
return createMemoryPaths(destination);
|
|
@@ -11760,14 +11772,14 @@ function resolveLocked(workspace, hooks) {
|
|
|
11760
11772
|
`);
|
|
11761
11773
|
syncDirectory(workspace.path);
|
|
11762
11774
|
removeEmptyDirectories(destination);
|
|
11763
|
-
|
|
11775
|
+
fs10.renameSync(staging, destination);
|
|
11764
11776
|
syncDirectory(workspace.path);
|
|
11765
11777
|
return createMemoryPaths(destination);
|
|
11766
11778
|
}
|
|
11767
11779
|
function inspectTree(target, regularRootIsContent = false, treeRoot = target) {
|
|
11768
11780
|
let stat4;
|
|
11769
11781
|
try {
|
|
11770
|
-
stat4 =
|
|
11782
|
+
stat4 = fs10.lstatSync(target);
|
|
11771
11783
|
} catch (error51) {
|
|
11772
11784
|
if (error51.code === "ENOENT") return "missing";
|
|
11773
11785
|
throw error51;
|
|
@@ -11776,7 +11788,7 @@ function inspectTree(target, regularRootIsContent = false, treeRoot = target) {
|
|
|
11776
11788
|
if (nodeKind === "unsafe") return "unsafe";
|
|
11777
11789
|
if (nodeKind === "file") return regularRootIsContent ? "content" : "unsafe";
|
|
11778
11790
|
let content = false;
|
|
11779
|
-
for (const entry of
|
|
11791
|
+
for (const entry of fs10.readdirSync(target, { withFileTypes: true })) {
|
|
11780
11792
|
const entryPath = path18__default.join(target, entry.name);
|
|
11781
11793
|
if (entry.isSymbolicLink()) {
|
|
11782
11794
|
if (readSafeFileSymlink(treeRoot, entryPath) === null) return "unsafe";
|
|
@@ -11796,7 +11808,7 @@ function inspectTree(target, regularRootIsContent = false, treeRoot = target) {
|
|
|
11796
11808
|
function readMarker(markerPath) {
|
|
11797
11809
|
let stat4;
|
|
11798
11810
|
try {
|
|
11799
|
-
stat4 =
|
|
11811
|
+
stat4 = fs10.lstatSync(markerPath);
|
|
11800
11812
|
} catch (error51) {
|
|
11801
11813
|
if (error51.code === "ENOENT") return null;
|
|
11802
11814
|
throw error51;
|
|
@@ -11804,7 +11816,7 @@ function readMarker(markerPath) {
|
|
|
11804
11816
|
if (!stat4.isFile() || stat4.isSymbolicLink()) throw new Error("Unsafe Fleet Wiki migration marker");
|
|
11805
11817
|
let value;
|
|
11806
11818
|
try {
|
|
11807
|
-
value = JSON.parse(
|
|
11819
|
+
value = JSON.parse(fs10.readFileSync(markerPath, "utf8"));
|
|
11808
11820
|
} catch {
|
|
11809
11821
|
throw new Error("Invalid Fleet Wiki migration marker");
|
|
11810
11822
|
}
|
|
@@ -11814,29 +11826,29 @@ function readMarker(markerPath) {
|
|
|
11814
11826
|
return record4;
|
|
11815
11827
|
}
|
|
11816
11828
|
function copyTree(source, destination, hooks, sourceRoot = source) {
|
|
11817
|
-
|
|
11818
|
-
for (const entry of
|
|
11829
|
+
fs10.mkdirSync(destination, { recursive: true });
|
|
11830
|
+
for (const entry of fs10.readdirSync(source, { withFileTypes: true })) {
|
|
11819
11831
|
const from = path18__default.join(source, entry.name);
|
|
11820
11832
|
const to = path18__default.join(destination, entry.name);
|
|
11821
|
-
const stat4 =
|
|
11833
|
+
const stat4 = fs10.lstatSync(from);
|
|
11822
11834
|
if (stat4.isSymbolicLink()) {
|
|
11823
11835
|
const target = readSafeFileSymlink(sourceRoot, from);
|
|
11824
11836
|
if (target === null) throw new Error("Unsafe Fleet Wiki legacy source state");
|
|
11825
|
-
|
|
11837
|
+
fs10.symlinkSync(target, to, "file");
|
|
11826
11838
|
continue;
|
|
11827
11839
|
}
|
|
11828
11840
|
const nodeKind = classifyWikiWorkspaceNodeForTest(stat4);
|
|
11829
11841
|
if (nodeKind === "unsafe") throw new Error("Unsafe Fleet Wiki legacy source state");
|
|
11830
11842
|
if (nodeKind === "directory") copyTree(from, to, hooks, sourceRoot);
|
|
11831
11843
|
else {
|
|
11832
|
-
|
|
11844
|
+
fs10.copyFileSync(from, to);
|
|
11833
11845
|
syncFile(to);
|
|
11834
11846
|
}
|
|
11835
11847
|
}
|
|
11836
11848
|
syncDirectory(destination);
|
|
11837
11849
|
}
|
|
11838
11850
|
function readSafeFileSymlink(treeRoot, linkPath) {
|
|
11839
|
-
const target =
|
|
11851
|
+
const target = fs10.readlinkSync(linkPath);
|
|
11840
11852
|
if (path18__default.posix.isAbsolute(target) || path18__default.win32.isAbsolute(target)) return null;
|
|
11841
11853
|
const lexicalRoot = path18__default.resolve(treeRoot);
|
|
11842
11854
|
const lexicalTarget = path18__default.resolve(path18__default.dirname(linkPath), target);
|
|
@@ -11845,9 +11857,9 @@ function readSafeFileSymlink(treeRoot, linkPath) {
|
|
|
11845
11857
|
let canonicalTarget;
|
|
11846
11858
|
let targetStat;
|
|
11847
11859
|
try {
|
|
11848
|
-
canonicalRoot =
|
|
11849
|
-
canonicalTarget =
|
|
11850
|
-
targetStat =
|
|
11860
|
+
canonicalRoot = fs10.realpathSync(treeRoot);
|
|
11861
|
+
canonicalTarget = fs10.realpathSync(linkPath);
|
|
11862
|
+
targetStat = fs10.statSync(linkPath);
|
|
11851
11863
|
} catch (error51) {
|
|
11852
11864
|
if (error51.code === "ENOENT") return null;
|
|
11853
11865
|
throw error51;
|
|
@@ -11869,19 +11881,19 @@ function removeEmptyDirectories(target) {
|
|
|
11869
11881
|
const state = inspectTree(target, true);
|
|
11870
11882
|
if (state === "missing") return;
|
|
11871
11883
|
if (state === "unsafe") throw new Error("Unsafe Fleet Wiki destination state");
|
|
11872
|
-
if (state === "empty")
|
|
11884
|
+
if (state === "empty") fs10.rmSync(target, { recursive: true, force: false });
|
|
11873
11885
|
}
|
|
11874
11886
|
function removePriorStaging(workspacePath, stagingEntries) {
|
|
11875
|
-
for (const name of stagingEntries)
|
|
11887
|
+
for (const name of stagingEntries) fs10.rmSync(path18__default.join(workspacePath, name), { recursive: true, force: false });
|
|
11876
11888
|
}
|
|
11877
11889
|
function inspectReservedControlState(workspacePath) {
|
|
11878
11890
|
const stagingEntries = [];
|
|
11879
|
-
for (const entry of
|
|
11891
|
+
for (const entry of fs10.readdirSync(workspacePath, { withFileTypes: true })) {
|
|
11880
11892
|
if (entry.name.startsWith(`${MARKER_NAME}.`)) {
|
|
11881
11893
|
const residuePath = path18__default.join(workspacePath, entry.name);
|
|
11882
|
-
const residue =
|
|
11894
|
+
const residue = fs10.lstatSync(residuePath);
|
|
11883
11895
|
if (MARKER_TEMP_REGEXP.test(entry.name) && residue.isFile() && !residue.isSymbolicLink()) {
|
|
11884
|
-
|
|
11896
|
+
fs10.unlinkSync(residuePath);
|
|
11885
11897
|
continue;
|
|
11886
11898
|
}
|
|
11887
11899
|
throw new Error("Unsafe Fleet Wiki migration marker control state");
|
|
@@ -11895,33 +11907,33 @@ function inspectReservedControlState(workspacePath) {
|
|
|
11895
11907
|
}
|
|
11896
11908
|
function writeAtomic2(target, contents) {
|
|
11897
11909
|
const temporary = `${target}.${randomUUID()}.tmp`;
|
|
11898
|
-
|
|
11910
|
+
fs10.writeFileSync(temporary, contents, { mode: 384 });
|
|
11899
11911
|
syncFile(temporary);
|
|
11900
|
-
|
|
11912
|
+
fs10.renameSync(temporary, target);
|
|
11901
11913
|
}
|
|
11902
11914
|
function fsyncBestEffort(fd) {
|
|
11903
11915
|
try {
|
|
11904
|
-
|
|
11916
|
+
fs10.fsyncSync(fd);
|
|
11905
11917
|
} catch (error51) {
|
|
11906
11918
|
const code = error51.code;
|
|
11907
11919
|
if (typeof code !== "string" || !IGNORED_FSYNC_ERROR_CODES2.has(code)) throw error51;
|
|
11908
11920
|
}
|
|
11909
11921
|
}
|
|
11910
11922
|
function syncFile(target) {
|
|
11911
|
-
const fd =
|
|
11923
|
+
const fd = fs10.openSync(target, "r");
|
|
11912
11924
|
try {
|
|
11913
11925
|
fsyncBestEffort(fd);
|
|
11914
11926
|
} finally {
|
|
11915
|
-
|
|
11927
|
+
fs10.closeSync(fd);
|
|
11916
11928
|
}
|
|
11917
11929
|
}
|
|
11918
11930
|
function syncDirectory(target) {
|
|
11919
11931
|
if (!shouldSyncDirectoryForTest(process.platform)) return;
|
|
11920
|
-
const fd =
|
|
11932
|
+
const fd = fs10.openSync(target, "r");
|
|
11921
11933
|
try {
|
|
11922
11934
|
fsyncBestEffort(fd);
|
|
11923
11935
|
} finally {
|
|
11924
|
-
|
|
11936
|
+
fs10.closeSync(fd);
|
|
11925
11937
|
}
|
|
11926
11938
|
}
|
|
11927
11939
|
function shouldSyncDirectoryForTest(platform) {
|
|
@@ -12352,7 +12364,7 @@ function createConsoleSettingsStore(deps = {}) {
|
|
|
12352
12364
|
const paths = deps.paths ?? createConsoleDataPaths();
|
|
12353
12365
|
const createStore = deps.createStore ?? createDurableJsonStore;
|
|
12354
12366
|
const randomInt = deps.randomInt ?? crypto5.randomInt;
|
|
12355
|
-
const readFile7 = deps.readFile ?? ((file2) =>
|
|
12367
|
+
const readFile7 = deps.readFile ?? ((file2) => fs10__default.readFileSync(file2, "utf8"));
|
|
12356
12368
|
const base = createStore({
|
|
12357
12369
|
filePath: paths.settingsFile,
|
|
12358
12370
|
lockDir: path18__default.join(paths.dir, SETTINGS_LOCK_DIR_NAME),
|
|
@@ -13557,7 +13569,7 @@ function formatCookie(name, value, secure, maxAgeSeconds) {
|
|
|
13557
13569
|
var REMOTE_DIR = "remote";
|
|
13558
13570
|
var FILE_MODE = 384;
|
|
13559
13571
|
function createRemoteStorage(consoleDir, deps = {}) {
|
|
13560
|
-
const fileSystem = deps.fileSystem ??
|
|
13572
|
+
const fileSystem = deps.fileSystem ?? fs10__default;
|
|
13561
13573
|
const ensureDirectory = deps.ensureDirectory ?? ensureSafeDirectory;
|
|
13562
13574
|
const directory = path18__default.join(consoleDir, REMOTE_DIR);
|
|
13563
13575
|
return {
|
|
@@ -13587,7 +13599,7 @@ function hashPairingSecret(secret) {
|
|
|
13587
13599
|
}
|
|
13588
13600
|
function createPairedDeviceStore(consoleDir, deps = {}) {
|
|
13589
13601
|
const storage = createRemoteStorage(consoleDir, deps);
|
|
13590
|
-
const readFile7 = deps.readFile ?? ((file2) =>
|
|
13602
|
+
const readFile7 = deps.readFile ?? ((file2) => fs10__default.readFileSync(file2, "utf8"));
|
|
13591
13603
|
const now = deps.now ?? Date.now;
|
|
13592
13604
|
const randomId = deps.randomId ?? (() => crypto5.randomBytes(8).toString("hex"));
|
|
13593
13605
|
const randomSecret = deps.randomSecret ?? (() => crypto5.randomBytes(32).toString("base64url"));
|
|
@@ -13675,6 +13687,168 @@ function isStoredDevice(value) {
|
|
|
13675
13687
|
const entry = value;
|
|
13676
13688
|
return typeof entry.id === "string" && entry.id.length > 0 && typeof entry.secretHash === "string" && /^[0-9a-f]{64}$/u.test(entry.secretHash) && (entry.audience === "local" || entry.audience === "remote") && (entry.access === "full" || entry.access === "monitoring") && (entry.device === null || typeof entry.device === "string") && typeof entry.pairedAt === "number" && Number.isFinite(entry.pairedAt) && typeof entry.lastSeenAt === "number" && Number.isFinite(entry.lastSeenAt);
|
|
13677
13689
|
}
|
|
13690
|
+
|
|
13691
|
+
// access-protocol/index.ts
|
|
13692
|
+
var ACCESS_LINK_SCHEME = "fleet:";
|
|
13693
|
+
var ACCESS_LINK_HOST = "join";
|
|
13694
|
+
var ACCESS_LINK_PREFIX = "fleet://join?code=";
|
|
13695
|
+
var ACCESS_LINK_VERSION = 1;
|
|
13696
|
+
var ACCESS_JOIN_PATH = "/api/v1/join";
|
|
13697
|
+
var MAX_ACCESS_LABEL_LENGTH = 48;
|
|
13698
|
+
var MAX_ACCESS_LINK_LENGTH = 4096;
|
|
13699
|
+
var ACCESS_TOKEN = /^[A-Za-z0-9_-]{16,512}$/u;
|
|
13700
|
+
var CERTIFICATE_FINGERPRINT = /^[0-9A-F]{64}$/u;
|
|
13701
|
+
var PAYLOAD_KEYS = ["v", "endpoint", "token", "fingerprint", "label"];
|
|
13702
|
+
var BASE64_URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
13703
|
+
var BASE64_URL_DECODE = createBase64UrlDecodeTable();
|
|
13704
|
+
function encodeAccessLink(payload) {
|
|
13705
|
+
const envelope = {
|
|
13706
|
+
v: ACCESS_LINK_VERSION,
|
|
13707
|
+
endpoint: payload.endpoint,
|
|
13708
|
+
token: payload.token,
|
|
13709
|
+
fingerprint: normalizeFingerprint(payload.fingerprint),
|
|
13710
|
+
label: sanitizeAccessLabel(payload.label)
|
|
13711
|
+
};
|
|
13712
|
+
return `${ACCESS_LINK_PREFIX}${toBase64Url(new TextEncoder().encode(JSON.stringify(envelope)))}`;
|
|
13713
|
+
}
|
|
13714
|
+
function parseAccessLink(input) {
|
|
13715
|
+
if (typeof input !== "string") throw invalidLink();
|
|
13716
|
+
const candidate = input.trim();
|
|
13717
|
+
if (candidate.length === 0 || candidate.length > MAX_ACCESS_LINK_LENGTH) throw invalidLink();
|
|
13718
|
+
if (containsDisallowedLinkWhitespace(candidate)) throw invalidLink();
|
|
13719
|
+
let url2;
|
|
13720
|
+
try {
|
|
13721
|
+
url2 = new URL(candidate);
|
|
13722
|
+
} catch {
|
|
13723
|
+
throw invalidLink();
|
|
13724
|
+
}
|
|
13725
|
+
if (url2.protocol !== ACCESS_LINK_SCHEME || url2.username || url2.password || url2.hash) throw invalidLink();
|
|
13726
|
+
if (url2.hostname !== ACCESS_LINK_HOST || url2.port !== "" || url2.pathname !== "") throw invalidLink();
|
|
13727
|
+
const keys = [...url2.searchParams.keys()];
|
|
13728
|
+
if (keys.length !== 1 || keys[0] !== "code") throw invalidLink();
|
|
13729
|
+
return readPayload(decodePayload(url2.searchParams.get("code") ?? ""));
|
|
13730
|
+
}
|
|
13731
|
+
function decodePayload(code) {
|
|
13732
|
+
if (!/^[A-Za-z0-9_-]+$/u.test(code)) throw invalidLink();
|
|
13733
|
+
let text;
|
|
13734
|
+
try {
|
|
13735
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(fromBase64Url(code));
|
|
13736
|
+
} catch {
|
|
13737
|
+
throw invalidLink();
|
|
13738
|
+
}
|
|
13739
|
+
try {
|
|
13740
|
+
return JSON.parse(text);
|
|
13741
|
+
} catch {
|
|
13742
|
+
throw invalidLink();
|
|
13743
|
+
}
|
|
13744
|
+
}
|
|
13745
|
+
function readPayload(value) {
|
|
13746
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw invalidLink();
|
|
13747
|
+
const entry = value;
|
|
13748
|
+
const keys = Object.keys(entry);
|
|
13749
|
+
if (keys.length !== PAYLOAD_KEYS.length || !PAYLOAD_KEYS.every((key) => keys.includes(key))) throw invalidLink();
|
|
13750
|
+
if (entry.v !== ACCESS_LINK_VERSION) throw invalidLink();
|
|
13751
|
+
if (typeof entry.endpoint !== "string" || typeof entry.token !== "string" || typeof entry.fingerprint !== "string" || typeof entry.label !== "string") throw invalidLink();
|
|
13752
|
+
const endpoint = readEndpoint(entry.endpoint);
|
|
13753
|
+
const token = entry.token;
|
|
13754
|
+
const fingerprint = normalizeFingerprint(entry.fingerprint);
|
|
13755
|
+
if (!ACCESS_TOKEN.test(token) || !CERTIFICATE_FINGERPRINT.test(fingerprint)) throw invalidLink();
|
|
13756
|
+
const label = sanitizeAccessLabel(entry.label);
|
|
13757
|
+
if (label.length === 0) throw invalidLink();
|
|
13758
|
+
return {
|
|
13759
|
+
origin: endpoint.origin,
|
|
13760
|
+
hostname: pinHostname(endpoint.hostname),
|
|
13761
|
+
port: endpoint.port,
|
|
13762
|
+
label,
|
|
13763
|
+
consoleUrl: new URL("/console/", endpoint.origin).toString(),
|
|
13764
|
+
joinUrl: new URL(ACCESS_JOIN_PATH, endpoint.origin).toString(),
|
|
13765
|
+
token,
|
|
13766
|
+
fingerprint
|
|
13767
|
+
};
|
|
13768
|
+
}
|
|
13769
|
+
function readEndpoint(value) {
|
|
13770
|
+
let url2;
|
|
13771
|
+
try {
|
|
13772
|
+
url2 = new URL(value);
|
|
13773
|
+
} catch {
|
|
13774
|
+
throw invalidLink();
|
|
13775
|
+
}
|
|
13776
|
+
if (url2.protocol !== "https:" || url2.username || url2.password || url2.search || url2.hash) throw invalidLink();
|
|
13777
|
+
if (url2.pathname !== "/" && url2.pathname !== "") throw invalidLink();
|
|
13778
|
+
if (url2.hostname.length === 0) throw invalidLink();
|
|
13779
|
+
const port = url2.port === "" ? 443 : Number(url2.port);
|
|
13780
|
+
if (!Number.isSafeInteger(port) || port < 1 || port > 65535) throw invalidLink();
|
|
13781
|
+
return { origin: url2.origin, hostname: url2.hostname, port };
|
|
13782
|
+
}
|
|
13783
|
+
function pinHostname(hostname5) {
|
|
13784
|
+
const unwrapped = hostname5.startsWith("[") && hostname5.endsWith("]") ? hostname5.slice(1, -1) : hostname5;
|
|
13785
|
+
return unwrapped.toLowerCase();
|
|
13786
|
+
}
|
|
13787
|
+
function normalizeFingerprint(value) {
|
|
13788
|
+
return value.replace(/[^0-9a-fA-F]/gu, "").toUpperCase();
|
|
13789
|
+
}
|
|
13790
|
+
function sanitizeAccessLabel(value) {
|
|
13791
|
+
return Array.from(value).filter((character) => !isDisallowedAccessLabelCharacter(character.codePointAt(0))).join("").replace(/\s+/gu, " ").trim().slice(0, MAX_ACCESS_LABEL_LENGTH);
|
|
13792
|
+
}
|
|
13793
|
+
function containsDisallowedLinkWhitespace(value) {
|
|
13794
|
+
for (const character of value) {
|
|
13795
|
+
const codePoint = character.codePointAt(0);
|
|
13796
|
+
if (codePoint <= 31 || codePoint === 127 || isWhitespaceCharacter(character)) return true;
|
|
13797
|
+
}
|
|
13798
|
+
return false;
|
|
13799
|
+
}
|
|
13800
|
+
function isWhitespaceCharacter(character) {
|
|
13801
|
+
return character.trim().length === 0;
|
|
13802
|
+
}
|
|
13803
|
+
function isDisallowedAccessLabelCharacter(codePoint) {
|
|
13804
|
+
return codePoint <= 31 || codePoint >= 127 && codePoint <= 159 || codePoint >= 8203 && codePoint <= 8207 || codePoint === 8232 || codePoint === 8233 || codePoint >= 8234 && codePoint <= 8238 || codePoint >= 8294 && codePoint <= 8297;
|
|
13805
|
+
}
|
|
13806
|
+
function toBase64Url(bytes) {
|
|
13807
|
+
let encoded = "";
|
|
13808
|
+
for (let index = 0; index < bytes.length; index += 3) {
|
|
13809
|
+
const first = bytes[index];
|
|
13810
|
+
const second = bytes[index + 1];
|
|
13811
|
+
const third = bytes[index + 2];
|
|
13812
|
+
encoded += BASE64_URL_ALPHABET[first >> 2];
|
|
13813
|
+
encoded += BASE64_URL_ALPHABET[(first & 3) << 4 | (second ?? 0) >> 4];
|
|
13814
|
+
if (second !== void 0) encoded += BASE64_URL_ALPHABET[(second & 15) << 2 | (third ?? 0) >> 6];
|
|
13815
|
+
if (third !== void 0) encoded += BASE64_URL_ALPHABET[third & 63];
|
|
13816
|
+
}
|
|
13817
|
+
return encoded;
|
|
13818
|
+
}
|
|
13819
|
+
function fromBase64Url(value) {
|
|
13820
|
+
if (value.length % 4 === 1) throw invalidLink();
|
|
13821
|
+
const bytes = new Uint8Array(Math.floor(value.length * 6 / 8));
|
|
13822
|
+
let buffer = 0;
|
|
13823
|
+
let bits = 0;
|
|
13824
|
+
let offset = 0;
|
|
13825
|
+
for (const character of value) {
|
|
13826
|
+
const decoded = BASE64_URL_DECODE[character.charCodeAt(0)] ?? -1;
|
|
13827
|
+
if (decoded < 0) throw invalidLink();
|
|
13828
|
+
buffer = buffer << 6 | decoded;
|
|
13829
|
+
bits += 6;
|
|
13830
|
+
if (bits >= 8) {
|
|
13831
|
+
bits -= 8;
|
|
13832
|
+
bytes[offset] = buffer >> bits & 255;
|
|
13833
|
+
offset += 1;
|
|
13834
|
+
}
|
|
13835
|
+
}
|
|
13836
|
+
if (bits > 0 && (buffer & (1 << bits) - 1) !== 0) throw invalidLink();
|
|
13837
|
+
return bytes;
|
|
13838
|
+
}
|
|
13839
|
+
function createBase64UrlDecodeTable() {
|
|
13840
|
+
const table = new Int16Array(128);
|
|
13841
|
+
table.fill(-1);
|
|
13842
|
+
for (let index = 0; index < BASE64_URL_ALPHABET.length; index += 1) {
|
|
13843
|
+
table[BASE64_URL_ALPHABET.charCodeAt(index)] = index;
|
|
13844
|
+
}
|
|
13845
|
+
return table;
|
|
13846
|
+
}
|
|
13847
|
+
function invalidLink() {
|
|
13848
|
+
return new Error("pairing_target_invalid");
|
|
13849
|
+
}
|
|
13850
|
+
|
|
13851
|
+
// core/host/remote-discovery.ts
|
|
13678
13852
|
function listRemoteInterfaces(interfaces = os4__default.networkInterfaces()) {
|
|
13679
13853
|
const candidates = [];
|
|
13680
13854
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -13698,6 +13872,32 @@ function labelFor(interfaceName) {
|
|
|
13698
13872
|
function sanitizeName(value) {
|
|
13699
13873
|
return value.replace(/[^A-Za-z0-9._-]/gu, "").slice(0, 24) || "interface";
|
|
13700
13874
|
}
|
|
13875
|
+
var REMOTE_PROBE_TIMEOUT_MS = 6e3;
|
|
13876
|
+
function probeRemoteIdentity(hostname5, port, expected, timeoutMs = REMOTE_PROBE_TIMEOUT_MS) {
|
|
13877
|
+
return new Promise((resolve3) => {
|
|
13878
|
+
const settle = (result) => {
|
|
13879
|
+
socket.destroy();
|
|
13880
|
+
resolve3(result);
|
|
13881
|
+
};
|
|
13882
|
+
const socket = tls.connect({
|
|
13883
|
+
host: hostname5,
|
|
13884
|
+
port,
|
|
13885
|
+
rejectUnauthorized: false,
|
|
13886
|
+
// IP 리터럴에는 SNI를 붙이지 않는다 — 규격상 SNI는 이름에만 쓴다.
|
|
13887
|
+
...net3.isIP(hostname5) === 0 ? { servername: hostname5 } : {}
|
|
13888
|
+
}, () => {
|
|
13889
|
+
const certificate = socket.getPeerX509Certificate();
|
|
13890
|
+
if (!certificate) {
|
|
13891
|
+
settle({ state: "unreachable" });
|
|
13892
|
+
return;
|
|
13893
|
+
}
|
|
13894
|
+
const presented = normalizeFingerprint(certificate.fingerprint256);
|
|
13895
|
+
settle(presented === normalizeFingerprint(expected) ? { state: "match" } : { state: "mismatch", presented });
|
|
13896
|
+
});
|
|
13897
|
+
socket.setTimeout(timeoutMs, () => settle({ state: "unreachable" }));
|
|
13898
|
+
socket.on("error", () => settle({ state: "unreachable" }));
|
|
13899
|
+
});
|
|
13900
|
+
}
|
|
13701
13901
|
|
|
13702
13902
|
// core/host/codex/workspace-routes.ts
|
|
13703
13903
|
function createCodexWorkspaceRouter(deps) {
|
|
@@ -14422,7 +14622,7 @@ function isOriginAllowed(origin, allowedOrigins, serverPort) {
|
|
|
14422
14622
|
if (Number(parsed.port) !== serverPort) return false;
|
|
14423
14623
|
const normalizedHost = normalizeOriginHostname(parsed.hostname);
|
|
14424
14624
|
if (!normalizedHost) return false;
|
|
14425
|
-
return allowedOrigins.has(`${parsed.protocol}//${
|
|
14625
|
+
return allowedOrigins.has(`${parsed.protocol}//${net3.isIP(normalizedHost) === 6 ? `[${normalizedHost}]` : normalizedHost}:${serverPort}`);
|
|
14426
14626
|
}
|
|
14427
14627
|
function sendJson(response, statusCode, body2) {
|
|
14428
14628
|
response.writeHead(statusCode, withSecurityHeaders(JSON_HEADERS));
|
|
@@ -14444,7 +14644,7 @@ function normalizeOriginHostname(hostname5) {
|
|
|
14444
14644
|
const unbracketed = stripIpv6Brackets(hostname5).toLowerCase();
|
|
14445
14645
|
if (unbracketed.includes("%")) return null;
|
|
14446
14646
|
if (unbracketed.startsWith("::ffff:")) return null;
|
|
14447
|
-
if (
|
|
14647
|
+
if (net3.isIP(unbracketed) === 6) {
|
|
14448
14648
|
try {
|
|
14449
14649
|
return stripIpv6Brackets(new URL(`http://[${unbracketed}]:1`).hostname).toLowerCase();
|
|
14450
14650
|
} catch {
|
|
@@ -33602,6 +33802,11 @@ function hasClaudeOneMillionMarker(modelId) {
|
|
|
33602
33802
|
function stripClaudeOneMillionMarker(modelId) {
|
|
33603
33803
|
return modelId.replace(/\[1m\]$/i, "");
|
|
33604
33804
|
}
|
|
33805
|
+
var CLAUDE_CLIENT_IDENTITY_SENTENCES = [
|
|
33806
|
+
"You are Claude Code, Anthropic's official CLI for Claude.",
|
|
33807
|
+
"You are a Claude agent, built on Anthropic's Claude Agent SDK."
|
|
33808
|
+
];
|
|
33809
|
+
Math.max(...CLAUDE_CLIENT_IDENTITY_SENTENCES.map((sentence) => sentence.length)) + 16;
|
|
33605
33810
|
var benchmarks_default = {
|
|
33606
33811
|
version: 2,
|
|
33607
33812
|
sources: {
|
|
@@ -33821,6 +34026,46 @@ var models_default = {
|
|
|
33821
34026
|
version: 1,
|
|
33822
34027
|
updatedAt: "2026-08-22T00:00:00Z",
|
|
33823
34028
|
providers: {
|
|
34029
|
+
antigravity: {
|
|
34030
|
+
name: "Antigravity",
|
|
34031
|
+
defaultModel: "gemini-3.7-flash",
|
|
34032
|
+
source: "live POST https://daily-cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels read with the credential the Antigravity CLI (agy 1.1.18) owns, 2026-08-22; the same read reported defaultAgentModelId gemini-3.7-flash-high and a deprecatedModelIds entry mapping gemini-3.1-pro-high to gemini-pro-agent, and a live streamGenerateContent probe on that date confirmed gemini-3.1-pro-high is refused with INVALID_ARGUMENT while gemini-pro-agent answers. Effort spelling was measured per model on one fixed prompt: gemini-3.7-flash-tiered honours generationConfig.thinkingConfig.thinkingLevel (343 / 407 / 434 reasoning tokens at low / medium / high) so its ladder is a request field, while Gemini 3.1 Pro encodes the rung in the wire id. thinkingLevel accepts low, medium, and high only: minimal and max are both refused. Claude and GPT-OSS models are served by the same subscription but are deliberately not exposed here",
|
|
34033
|
+
models: [
|
|
34034
|
+
{
|
|
34035
|
+
modelId: "gemini-3.7-flash",
|
|
34036
|
+
name: "Gemini-3.7-Flash",
|
|
34037
|
+
capabilityClass: "light",
|
|
34038
|
+
providerModelId: "gemini-3.7-flash-tiered",
|
|
34039
|
+
contextWindow: 1048576,
|
|
34040
|
+
effort: {
|
|
34041
|
+
supported: true,
|
|
34042
|
+
levels: [
|
|
34043
|
+
"low",
|
|
34044
|
+
"medium",
|
|
34045
|
+
"high"
|
|
34046
|
+
]
|
|
34047
|
+
}
|
|
34048
|
+
},
|
|
34049
|
+
{
|
|
34050
|
+
modelId: "gemini-3.1-pro",
|
|
34051
|
+
name: "Gemini-3.1-Pro",
|
|
34052
|
+
capabilityClass: "flagship",
|
|
34053
|
+
providerModelId: "gemini-3.1-pro-low",
|
|
34054
|
+
contextWindow: 1048576,
|
|
34055
|
+
effort: {
|
|
34056
|
+
supported: true,
|
|
34057
|
+
levels: [
|
|
34058
|
+
"low",
|
|
34059
|
+
"high"
|
|
34060
|
+
],
|
|
34061
|
+
upstreamModelIds: {
|
|
34062
|
+
low: "gemini-3.1-pro-low",
|
|
34063
|
+
high: "gemini-pro-agent"
|
|
34064
|
+
}
|
|
34065
|
+
}
|
|
34066
|
+
}
|
|
34067
|
+
]
|
|
34068
|
+
},
|
|
33824
34069
|
codex: {
|
|
33825
34070
|
name: "Codex",
|
|
33826
34071
|
defaultModel: "gpt-5.6-sol",
|
|
@@ -34816,7 +35061,7 @@ var models_default = {
|
|
|
34816
35061
|
}
|
|
34817
35062
|
}
|
|
34818
35063
|
};
|
|
34819
|
-
var GATEWAY_PROVIDERS = ["codex", "xai", "cursor", "opencode", "kimi"];
|
|
35064
|
+
var GATEWAY_PROVIDERS = ["codex", "xai", "cursor", "opencode", "antigravity", "kimi"];
|
|
34820
35065
|
var GATEWAY_MODEL_WIRES = ["anthropic", "responses", "chat-completions"];
|
|
34821
35066
|
var GATEWAY_REASONING_EFFORTS = [
|
|
34822
35067
|
"low",
|
|
@@ -34924,7 +35169,8 @@ var GatewayModelsRegistrySchema = external_exports.object({
|
|
|
34924
35169
|
cursor: GatewayProviderSchema,
|
|
34925
35170
|
kimi: GatewayProviderSchema,
|
|
34926
35171
|
opencode: GatewayProviderSchema,
|
|
34927
|
-
xai: GatewayProviderSchema
|
|
35172
|
+
xai: GatewayProviderSchema,
|
|
35173
|
+
antigravity: GatewayProviderSchema
|
|
34928
35174
|
}).strict(),
|
|
34929
35175
|
pricing: GatewayPricingRegistrySchema
|
|
34930
35176
|
}).strict();
|
|
@@ -34950,7 +35196,6 @@ var registry2 = (() => {
|
|
|
34950
35196
|
return parsed;
|
|
34951
35197
|
})();
|
|
34952
35198
|
var GATEWAY_MODELS_UPDATED_AT = registry2.updatedAt;
|
|
34953
|
-
registry2.pricing.observedAt;
|
|
34954
35199
|
Object.freeze(
|
|
34955
35200
|
Object.fromEntries(
|
|
34956
35201
|
Object.entries(registry2.pricing.models).map(([modelId, pricing]) => [
|
|
@@ -35197,8 +35442,8 @@ function validateRegistry(value) {
|
|
|
35197
35442
|
}
|
|
35198
35443
|
}
|
|
35199
35444
|
if (exactModelIds) {
|
|
35200
|
-
if (provider !== "cursor") {
|
|
35201
|
-
throw new Error(`Gateway effort model id overrides are only supported by Cursor: ${provider}/${model.modelId}`);
|
|
35445
|
+
if (provider !== "cursor" && provider !== "antigravity") {
|
|
35446
|
+
throw new Error(`Gateway effort model id overrides are only supported by Cursor and Antigravity: ${provider}/${model.modelId}`);
|
|
35202
35447
|
}
|
|
35203
35448
|
for (const effort of Object.keys(exactModelIds)) {
|
|
35204
35449
|
if (!model.effort.levels.includes(effort)) {
|
|
@@ -35299,6 +35544,18 @@ process.platform === "win32" ? constants.O_RDONLY : constants.O_RDONLY | constan
|
|
|
35299
35544
|
platform: process.platform,
|
|
35300
35545
|
homedir: os8.homedir,
|
|
35301
35546
|
env: process.env});
|
|
35547
|
+
var HOUR_MS = 36e5;
|
|
35548
|
+
var WEEK_MS = 7 * 24 * HOUR_MS;
|
|
35549
|
+
var SESSION_MS = 5 * HOUR_MS;
|
|
35550
|
+
var BUCKETS = Object.freeze({
|
|
35551
|
+
"gemini-5h": { id: "session", label: "Gemini", durationMs: SESSION_MS, reported: true },
|
|
35552
|
+
"gemini-weekly": { id: "weekly", label: "Gemini", durationMs: WEEK_MS, reported: true },
|
|
35553
|
+
"3p-5h": { id: "session", label: "Claude & GPT", durationMs: SESSION_MS, reported: false },
|
|
35554
|
+
"3p-weekly": { id: "weekly", label: "Claude & GPT", durationMs: WEEK_MS, reported: false }
|
|
35555
|
+
});
|
|
35556
|
+
Object.freeze(
|
|
35557
|
+
Object.keys(BUCKETS).filter((bucketId) => BUCKETS[bucketId]?.reported === true)
|
|
35558
|
+
);
|
|
35302
35559
|
var CURSOR_GREP_RECEIPT_PREFIX = "FLEET_CURSOR_GREP_V2:";
|
|
35303
35560
|
var CURSOR_GREP_RECEIPT_SCRIPT = String.raw`
|
|
35304
35561
|
const {spawn}=require("node:child_process");
|
|
@@ -37184,7 +37441,7 @@ async function canonicalizeTheaterPath(cwd) {
|
|
|
37184
37441
|
function canonicalizeTheaterPathSync(cwd) {
|
|
37185
37442
|
const resolved = path18__default.resolve(cwd);
|
|
37186
37443
|
try {
|
|
37187
|
-
return
|
|
37444
|
+
return fs10__default.realpathSync.native(resolved);
|
|
37188
37445
|
} catch {
|
|
37189
37446
|
return resolved;
|
|
37190
37447
|
}
|
|
@@ -37204,8 +37461,8 @@ var DIRECTORY_ENTRY_CAP = 500;
|
|
|
37204
37461
|
var WINDOWS_DRIVE_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
|
|
37205
37462
|
async function listTheaterFolders(requestedPath, deps = {}) {
|
|
37206
37463
|
const platform = deps.platform ?? process.platform;
|
|
37207
|
-
const stat4 = deps.stat ??
|
|
37208
|
-
const opendir = deps.opendir ??
|
|
37464
|
+
const stat4 = deps.stat ?? fs10__default.promises.stat;
|
|
37465
|
+
const opendir = deps.opendir ?? fs10__default.promises.opendir;
|
|
37209
37466
|
const targetPath = normalizeListPath(requestedPath, platform, deps);
|
|
37210
37467
|
const roots = await listRoots(platform, stat4);
|
|
37211
37468
|
const targetStat = await statDirectory(targetPath, stat4);
|
|
@@ -37316,7 +37573,7 @@ var GRANT_ID_BYTES = 24;
|
|
|
37316
37573
|
var DEFAULT_GRANT_TTL_MS2 = 6e4;
|
|
37317
37574
|
function createFolderGrantStore(deps = {}) {
|
|
37318
37575
|
const randomId = deps.randomId ?? (() => crypto5.randomBytes(GRANT_ID_BYTES).toString("base64url"));
|
|
37319
|
-
const statSync2 = deps.statSync ??
|
|
37576
|
+
const statSync2 = deps.statSync ?? fs10__default.statSync;
|
|
37320
37577
|
const ttlMs = deps.ttlMs ?? DEFAULT_GRANT_TTL_MS2;
|
|
37321
37578
|
const now = deps.now ?? Date.now;
|
|
37322
37579
|
const grants = /* @__PURE__ */ new Map();
|
|
@@ -37342,7 +37599,7 @@ function createFolderGrantStore(deps = {}) {
|
|
|
37342
37599
|
}
|
|
37343
37600
|
return { issue: issue3, consume };
|
|
37344
37601
|
}
|
|
37345
|
-
function validateAbsoluteDirectory(cwd, statSync2 =
|
|
37602
|
+
function validateAbsoluteDirectory(cwd, statSync2 = fs10__default.statSync) {
|
|
37346
37603
|
if (typeof cwd !== "string" || cwd.length === 0 || cwd.includes("\0")) throw new Error("invalid_folder");
|
|
37347
37604
|
if (isWindowsAmbiguousGrantPath(cwd) || !path18__default.isAbsolute(cwd)) throw new Error("invalid_folder");
|
|
37348
37605
|
const normalized = path18__default.resolve(cwd);
|
|
@@ -37726,13 +37983,13 @@ function isJsonRequest(request) {
|
|
|
37726
37983
|
return accept.includes("application/json") || requestedWith.toLowerCase() === "xmlhttprequest";
|
|
37727
37984
|
}
|
|
37728
37985
|
function formatHostForUrl(host) {
|
|
37729
|
-
return
|
|
37986
|
+
return net3.isIP(host) === 6 ? `[${host}]` : host;
|
|
37730
37987
|
}
|
|
37731
37988
|
function canonicalizeAllowedHost(host) {
|
|
37732
37989
|
const unbracketed = stripIpv6Brackets2(host).toLowerCase();
|
|
37733
37990
|
if (unbracketed.includes("%")) return null;
|
|
37734
37991
|
if (isIpv4MappedAddress(unbracketed)) return null;
|
|
37735
|
-
if (
|
|
37992
|
+
if (net3.isIP(unbracketed) === 6) {
|
|
37736
37993
|
try {
|
|
37737
37994
|
return stripIpv6Brackets2(new URL(`http://[${unbracketed}]:1`).hostname).toLowerCase();
|
|
37738
37995
|
} catch {
|
|
@@ -37746,7 +38003,7 @@ function enumerateWildcardAccessHosts(interfaces) {
|
|
|
37746
38003
|
for (const entries of Object.values(interfaces)) {
|
|
37747
38004
|
for (const entry of entries ?? []) {
|
|
37748
38005
|
if (entry.internal) continue;
|
|
37749
|
-
if (
|
|
38006
|
+
if (net3.isIP(entry.address) === 0) continue;
|
|
37750
38007
|
hosts.push(entry.address);
|
|
37751
38008
|
}
|
|
37752
38009
|
}
|
|
@@ -37780,7 +38037,7 @@ function parseHostHeader(value) {
|
|
|
37780
38037
|
const host = canonicalizeAllowedHost(parts[0] ?? "");
|
|
37781
38038
|
const port = Number(parts[1] ?? "");
|
|
37782
38039
|
if (!host || !Number.isInteger(port)) return null;
|
|
37783
|
-
if (
|
|
38040
|
+
if (net3.isIP(host) === 6) return null;
|
|
37784
38041
|
return { host, port };
|
|
37785
38042
|
}
|
|
37786
38043
|
function readRawHeaderValues(rawHeaders, name) {
|
|
@@ -38338,8 +38595,8 @@ function migrateAgentCliIds(state) {
|
|
|
38338
38595
|
function backupDurableStateBeforeAgentCliIdMigration(stateFilePath) {
|
|
38339
38596
|
const backupPath = `${stateFilePath}${BACKUP_FILE_SUFFIX}`;
|
|
38340
38597
|
try {
|
|
38341
|
-
if (!
|
|
38342
|
-
|
|
38598
|
+
if (!fs10__default.existsSync(stateFilePath) || fs10__default.existsSync(backupPath)) return;
|
|
38599
|
+
fs10__default.copyFileSync(stateFilePath, backupPath);
|
|
38343
38600
|
} catch (error51) {
|
|
38344
38601
|
console.warn(`[fleet-console] Agent CLI id migration backup skipped: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
38345
38602
|
}
|
|
@@ -38386,11 +38643,11 @@ function migrateLegacyCaptures(deps) {
|
|
|
38386
38643
|
function migrateLegacyCapturesStrict(deps) {
|
|
38387
38644
|
if (!path18__default.isAbsolute(deps.consoleDataDir)) return;
|
|
38388
38645
|
const capturesDir = path18__default.join(deps.consoleDataDir, LEGACY_CAPTURES_DIR_NAME);
|
|
38389
|
-
if (!
|
|
38646
|
+
if (!fs10__default.existsSync(capturesDir)) return;
|
|
38390
38647
|
let migrated = false;
|
|
38391
38648
|
let retained = false;
|
|
38392
38649
|
try {
|
|
38393
|
-
const entries =
|
|
38650
|
+
const entries = fs10__default.readdirSync(capturesDir);
|
|
38394
38651
|
for (const entry of entries) {
|
|
38395
38652
|
if (!entry.endsWith(".json")) continue;
|
|
38396
38653
|
const operationId = entry.slice(0, -".json".length);
|
|
@@ -38419,7 +38676,7 @@ function migrateLegacyCapturesStrict(deps) {
|
|
|
38419
38676
|
}
|
|
38420
38677
|
if ((!migrated || saved) && !retained) {
|
|
38421
38678
|
try {
|
|
38422
|
-
|
|
38679
|
+
fs10__default.rmSync(capturesDir, { recursive: true, force: true });
|
|
38423
38680
|
} catch (error51) {
|
|
38424
38681
|
console.warn(`[fleet-console] Legacy captures directory removal failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
38425
38682
|
}
|
|
@@ -38430,7 +38687,7 @@ function processCaptureFile(deps, capturesDir, operationId, entry) {
|
|
|
38430
38687
|
if (operation) {
|
|
38431
38688
|
if (hasProviderSession(operation.payload)) return { migrated: false, retained: false };
|
|
38432
38689
|
const filePath = path18__default.join(capturesDir, entry);
|
|
38433
|
-
const parsed = JSON.parse(
|
|
38690
|
+
const parsed = JSON.parse(fs10__default.readFileSync(filePath, "utf8"));
|
|
38434
38691
|
const providerSession = sanitizeProviderSession(parsed);
|
|
38435
38692
|
if (!providerSession) return { migrated: false, retained: false };
|
|
38436
38693
|
deps.operations.patch(operationId, {
|
|
@@ -38468,7 +38725,7 @@ var ENDPOINT_FILE = "listener.json";
|
|
|
38468
38725
|
var STORE_VERSION2 = 2;
|
|
38469
38726
|
function createRemoteEndpointStore(consoleDir, deps = {}) {
|
|
38470
38727
|
const storage = createRemoteStorage(consoleDir, deps);
|
|
38471
|
-
const readFile7 = deps.readFile ?? ((file2) =>
|
|
38728
|
+
const readFile7 = deps.readFile ?? ((file2) => fs10__default.readFileSync(file2, "utf8"));
|
|
38472
38729
|
let endpoint = read();
|
|
38473
38730
|
function read() {
|
|
38474
38731
|
try {
|
|
@@ -38508,168 +38765,6 @@ function sameEndpoint(left, right) {
|
|
|
38508
38765
|
function isBindablePort2(value) {
|
|
38509
38766
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 && value <= 65535;
|
|
38510
38767
|
}
|
|
38511
|
-
|
|
38512
|
-
// access-protocol/index.ts
|
|
38513
|
-
var ACCESS_LINK_SCHEME = "fleet:";
|
|
38514
|
-
var ACCESS_LINK_HOST = "join";
|
|
38515
|
-
var ACCESS_LINK_PREFIX = "fleet://join?code=";
|
|
38516
|
-
var ACCESS_LINK_VERSION = 1;
|
|
38517
|
-
var ACCESS_JOIN_PATH = "/api/v1/join";
|
|
38518
|
-
var MAX_ACCESS_LABEL_LENGTH = 48;
|
|
38519
|
-
var MAX_ACCESS_LINK_LENGTH = 4096;
|
|
38520
|
-
var ACCESS_TOKEN = /^[A-Za-z0-9_-]{16,512}$/u;
|
|
38521
|
-
var CERTIFICATE_FINGERPRINT = /^[0-9A-F]{64}$/u;
|
|
38522
|
-
var PAYLOAD_KEYS = ["v", "endpoint", "token", "fingerprint", "label"];
|
|
38523
|
-
var BASE64_URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
38524
|
-
var BASE64_URL_DECODE = createBase64UrlDecodeTable();
|
|
38525
|
-
function encodeAccessLink(payload) {
|
|
38526
|
-
const envelope = {
|
|
38527
|
-
v: ACCESS_LINK_VERSION,
|
|
38528
|
-
endpoint: payload.endpoint,
|
|
38529
|
-
token: payload.token,
|
|
38530
|
-
fingerprint: normalizeFingerprint(payload.fingerprint),
|
|
38531
|
-
label: sanitizeAccessLabel(payload.label)
|
|
38532
|
-
};
|
|
38533
|
-
return `${ACCESS_LINK_PREFIX}${toBase64Url(new TextEncoder().encode(JSON.stringify(envelope)))}`;
|
|
38534
|
-
}
|
|
38535
|
-
function parseAccessLink(input) {
|
|
38536
|
-
if (typeof input !== "string") throw invalidLink();
|
|
38537
|
-
const candidate = input.trim();
|
|
38538
|
-
if (candidate.length === 0 || candidate.length > MAX_ACCESS_LINK_LENGTH) throw invalidLink();
|
|
38539
|
-
if (containsDisallowedLinkWhitespace(candidate)) throw invalidLink();
|
|
38540
|
-
let url2;
|
|
38541
|
-
try {
|
|
38542
|
-
url2 = new URL(candidate);
|
|
38543
|
-
} catch {
|
|
38544
|
-
throw invalidLink();
|
|
38545
|
-
}
|
|
38546
|
-
if (url2.protocol !== ACCESS_LINK_SCHEME || url2.username || url2.password || url2.hash) throw invalidLink();
|
|
38547
|
-
if (url2.hostname !== ACCESS_LINK_HOST || url2.port !== "" || url2.pathname !== "") throw invalidLink();
|
|
38548
|
-
const keys = [...url2.searchParams.keys()];
|
|
38549
|
-
if (keys.length !== 1 || keys[0] !== "code") throw invalidLink();
|
|
38550
|
-
return readPayload(decodePayload(url2.searchParams.get("code") ?? ""));
|
|
38551
|
-
}
|
|
38552
|
-
function decodePayload(code) {
|
|
38553
|
-
if (!/^[A-Za-z0-9_-]+$/u.test(code)) throw invalidLink();
|
|
38554
|
-
let text;
|
|
38555
|
-
try {
|
|
38556
|
-
text = new TextDecoder("utf-8", { fatal: true }).decode(fromBase64Url(code));
|
|
38557
|
-
} catch {
|
|
38558
|
-
throw invalidLink();
|
|
38559
|
-
}
|
|
38560
|
-
try {
|
|
38561
|
-
return JSON.parse(text);
|
|
38562
|
-
} catch {
|
|
38563
|
-
throw invalidLink();
|
|
38564
|
-
}
|
|
38565
|
-
}
|
|
38566
|
-
function readPayload(value) {
|
|
38567
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw invalidLink();
|
|
38568
|
-
const entry = value;
|
|
38569
|
-
const keys = Object.keys(entry);
|
|
38570
|
-
if (keys.length !== PAYLOAD_KEYS.length || !PAYLOAD_KEYS.every((key) => keys.includes(key))) throw invalidLink();
|
|
38571
|
-
if (entry.v !== ACCESS_LINK_VERSION) throw invalidLink();
|
|
38572
|
-
if (typeof entry.endpoint !== "string" || typeof entry.token !== "string" || typeof entry.fingerprint !== "string" || typeof entry.label !== "string") throw invalidLink();
|
|
38573
|
-
const endpoint = readEndpoint(entry.endpoint);
|
|
38574
|
-
const token = entry.token;
|
|
38575
|
-
const fingerprint = normalizeFingerprint(entry.fingerprint);
|
|
38576
|
-
if (!ACCESS_TOKEN.test(token) || !CERTIFICATE_FINGERPRINT.test(fingerprint)) throw invalidLink();
|
|
38577
|
-
const label = sanitizeAccessLabel(entry.label);
|
|
38578
|
-
if (label.length === 0) throw invalidLink();
|
|
38579
|
-
return {
|
|
38580
|
-
origin: endpoint.origin,
|
|
38581
|
-
hostname: pinHostname(endpoint.hostname),
|
|
38582
|
-
port: endpoint.port,
|
|
38583
|
-
label,
|
|
38584
|
-
consoleUrl: new URL("/console/", endpoint.origin).toString(),
|
|
38585
|
-
joinUrl: new URL(ACCESS_JOIN_PATH, endpoint.origin).toString(),
|
|
38586
|
-
token,
|
|
38587
|
-
fingerprint
|
|
38588
|
-
};
|
|
38589
|
-
}
|
|
38590
|
-
function readEndpoint(value) {
|
|
38591
|
-
let url2;
|
|
38592
|
-
try {
|
|
38593
|
-
url2 = new URL(value);
|
|
38594
|
-
} catch {
|
|
38595
|
-
throw invalidLink();
|
|
38596
|
-
}
|
|
38597
|
-
if (url2.protocol !== "https:" || url2.username || url2.password || url2.search || url2.hash) throw invalidLink();
|
|
38598
|
-
if (url2.pathname !== "/" && url2.pathname !== "") throw invalidLink();
|
|
38599
|
-
if (url2.hostname.length === 0) throw invalidLink();
|
|
38600
|
-
const port = url2.port === "" ? 443 : Number(url2.port);
|
|
38601
|
-
if (!Number.isSafeInteger(port) || port < 1 || port > 65535) throw invalidLink();
|
|
38602
|
-
return { origin: url2.origin, hostname: url2.hostname, port };
|
|
38603
|
-
}
|
|
38604
|
-
function pinHostname(hostname5) {
|
|
38605
|
-
const unwrapped = hostname5.startsWith("[") && hostname5.endsWith("]") ? hostname5.slice(1, -1) : hostname5;
|
|
38606
|
-
return unwrapped.toLowerCase();
|
|
38607
|
-
}
|
|
38608
|
-
function normalizeFingerprint(value) {
|
|
38609
|
-
return value.replace(/[^0-9a-fA-F]/gu, "").toUpperCase();
|
|
38610
|
-
}
|
|
38611
|
-
function sanitizeAccessLabel(value) {
|
|
38612
|
-
return Array.from(value).filter((character) => !isDisallowedAccessLabelCharacter(character.codePointAt(0))).join("").replace(/\s+/gu, " ").trim().slice(0, MAX_ACCESS_LABEL_LENGTH);
|
|
38613
|
-
}
|
|
38614
|
-
function containsDisallowedLinkWhitespace(value) {
|
|
38615
|
-
for (const character of value) {
|
|
38616
|
-
const codePoint = character.codePointAt(0);
|
|
38617
|
-
if (codePoint <= 31 || codePoint === 127 || isWhitespaceCharacter(character)) return true;
|
|
38618
|
-
}
|
|
38619
|
-
return false;
|
|
38620
|
-
}
|
|
38621
|
-
function isWhitespaceCharacter(character) {
|
|
38622
|
-
return character.trim().length === 0;
|
|
38623
|
-
}
|
|
38624
|
-
function isDisallowedAccessLabelCharacter(codePoint) {
|
|
38625
|
-
return codePoint <= 31 || codePoint >= 127 && codePoint <= 159 || codePoint >= 8203 && codePoint <= 8207 || codePoint === 8232 || codePoint === 8233 || codePoint >= 8234 && codePoint <= 8238 || codePoint >= 8294 && codePoint <= 8297;
|
|
38626
|
-
}
|
|
38627
|
-
function toBase64Url(bytes) {
|
|
38628
|
-
let encoded = "";
|
|
38629
|
-
for (let index = 0; index < bytes.length; index += 3) {
|
|
38630
|
-
const first = bytes[index];
|
|
38631
|
-
const second = bytes[index + 1];
|
|
38632
|
-
const third = bytes[index + 2];
|
|
38633
|
-
encoded += BASE64_URL_ALPHABET[first >> 2];
|
|
38634
|
-
encoded += BASE64_URL_ALPHABET[(first & 3) << 4 | (second ?? 0) >> 4];
|
|
38635
|
-
if (second !== void 0) encoded += BASE64_URL_ALPHABET[(second & 15) << 2 | (third ?? 0) >> 6];
|
|
38636
|
-
if (third !== void 0) encoded += BASE64_URL_ALPHABET[third & 63];
|
|
38637
|
-
}
|
|
38638
|
-
return encoded;
|
|
38639
|
-
}
|
|
38640
|
-
function fromBase64Url(value) {
|
|
38641
|
-
if (value.length % 4 === 1) throw invalidLink();
|
|
38642
|
-
const bytes = new Uint8Array(Math.floor(value.length * 6 / 8));
|
|
38643
|
-
let buffer = 0;
|
|
38644
|
-
let bits = 0;
|
|
38645
|
-
let offset = 0;
|
|
38646
|
-
for (const character of value) {
|
|
38647
|
-
const decoded = BASE64_URL_DECODE[character.charCodeAt(0)] ?? -1;
|
|
38648
|
-
if (decoded < 0) throw invalidLink();
|
|
38649
|
-
buffer = buffer << 6 | decoded;
|
|
38650
|
-
bits += 6;
|
|
38651
|
-
if (bits >= 8) {
|
|
38652
|
-
bits -= 8;
|
|
38653
|
-
bytes[offset] = buffer >> bits & 255;
|
|
38654
|
-
offset += 1;
|
|
38655
|
-
}
|
|
38656
|
-
}
|
|
38657
|
-
if (bits > 0 && (buffer & (1 << bits) - 1) !== 0) throw invalidLink();
|
|
38658
|
-
return bytes;
|
|
38659
|
-
}
|
|
38660
|
-
function createBase64UrlDecodeTable() {
|
|
38661
|
-
const table = new Int16Array(128);
|
|
38662
|
-
table.fill(-1);
|
|
38663
|
-
for (let index = 0; index < BASE64_URL_ALPHABET.length; index += 1) {
|
|
38664
|
-
table[BASE64_URL_ALPHABET.charCodeAt(index)] = index;
|
|
38665
|
-
}
|
|
38666
|
-
return table;
|
|
38667
|
-
}
|
|
38668
|
-
function invalidLink() {
|
|
38669
|
-
return new Error("pairing_target_invalid");
|
|
38670
|
-
}
|
|
38671
|
-
|
|
38672
|
-
// core/host/remote-identity.ts
|
|
38673
38768
|
var CERTIFICATE_FILE = "identity-cert.pem";
|
|
38674
38769
|
var KEY_FILE = "identity-key.pem";
|
|
38675
38770
|
var META_FILE = "identity.json";
|
|
@@ -38677,7 +38772,7 @@ var VALIDITY_DAYS = 825;
|
|
|
38677
38772
|
var RENEW_BEFORE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
38678
38773
|
function createRemoteIdentityStore(consoleDir, deps = {}) {
|
|
38679
38774
|
const storage = createRemoteStorage(consoleDir, deps);
|
|
38680
|
-
const readFile7 = deps.readFile ?? ((file2) =>
|
|
38775
|
+
const readFile7 = deps.readFile ?? ((file2) => fs10__default.readFileSync(file2, "utf8"));
|
|
38681
38776
|
const generate = deps.generate ?? generateSelfSignedCertificate;
|
|
38682
38777
|
const now = deps.now ?? Date.now;
|
|
38683
38778
|
function read() {
|
|
@@ -38747,7 +38842,7 @@ var MAX_HOSTS = 64;
|
|
|
38747
38842
|
var HANDOFF_TTL_MS = 5 * 60 * 1e3;
|
|
38748
38843
|
function createRemoteHostStore(consoleDir, deps = {}) {
|
|
38749
38844
|
const storage = createRemoteStorage(consoleDir, deps);
|
|
38750
|
-
const readFile7 = deps.readFile ?? ((file2) =>
|
|
38845
|
+
const readFile7 = deps.readFile ?? ((file2) => fs10__default.readFileSync(file2, "utf8"));
|
|
38751
38846
|
const now = deps.now ?? Date.now;
|
|
38752
38847
|
const randomId = deps.randomId ?? (() => crypto5.randomUUID());
|
|
38753
38848
|
const pending = /* @__PURE__ */ new Map();
|
|
@@ -38898,32 +38993,6 @@ function normalizeRemoteJoinSource(address) {
|
|
|
38898
38993
|
const mapped = /^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/iu.exec(address);
|
|
38899
38994
|
return mapped === null ? address : mapped[1];
|
|
38900
38995
|
}
|
|
38901
|
-
var REMOTE_PROBE_TIMEOUT_MS = 6e3;
|
|
38902
|
-
function probeRemoteIdentity(hostname5, port, expected, timeoutMs = REMOTE_PROBE_TIMEOUT_MS) {
|
|
38903
|
-
return new Promise((resolve3) => {
|
|
38904
|
-
const settle = (result) => {
|
|
38905
|
-
socket.destroy();
|
|
38906
|
-
resolve3(result);
|
|
38907
|
-
};
|
|
38908
|
-
const socket = tls.connect({
|
|
38909
|
-
host: hostname5,
|
|
38910
|
-
port,
|
|
38911
|
-
rejectUnauthorized: false,
|
|
38912
|
-
// IP 리터럴에는 SNI를 붙이지 않는다 — 규격상 SNI는 이름에만 쓴다.
|
|
38913
|
-
...net2.isIP(hostname5) === 0 ? { servername: hostname5 } : {}
|
|
38914
|
-
}, () => {
|
|
38915
|
-
const certificate = socket.getPeerX509Certificate();
|
|
38916
|
-
if (!certificate) {
|
|
38917
|
-
settle({ state: "unreachable" });
|
|
38918
|
-
return;
|
|
38919
|
-
}
|
|
38920
|
-
const presented = normalizeFingerprint(certificate.fingerprint256);
|
|
38921
|
-
settle(presented === normalizeFingerprint(expected) ? { state: "match" } : { state: "mismatch", presented });
|
|
38922
|
-
});
|
|
38923
|
-
socket.setTimeout(timeoutMs, () => settle({ state: "unreachable" }));
|
|
38924
|
-
socket.on("error", () => settle({ state: "unreachable" }));
|
|
38925
|
-
});
|
|
38926
|
-
}
|
|
38927
38996
|
var WSL_ROOT = "\\\\wsl.localhost";
|
|
38928
38997
|
var WSL_TMP = "tmp";
|
|
38929
38998
|
var LOCK_FILE = "console.lock";
|
|
@@ -38936,7 +39005,7 @@ function isUsableDistroName(name) {
|
|
|
38936
39005
|
var WSL_LIST_TIMEOUT_MS = 3e3;
|
|
38937
39006
|
var REACHABLE_TIMEOUT_MS = 700;
|
|
38938
39007
|
async function listLocalConsoles(deps = {}) {
|
|
38939
|
-
const fileSystem = deps.fileSystem ??
|
|
39008
|
+
const fileSystem = deps.fileSystem ?? fs10__default;
|
|
38940
39009
|
const isAlive = deps.isAlive ?? processIsAlive;
|
|
38941
39010
|
const entries = [];
|
|
38942
39011
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -39046,7 +39115,7 @@ function portAnswers(origin) {
|
|
|
39046
39115
|
resolve3(false);
|
|
39047
39116
|
return;
|
|
39048
39117
|
}
|
|
39049
|
-
const socket =
|
|
39118
|
+
const socket = net3.connect({ host: url2.hostname, port: Number(url2.port) }, () => {
|
|
39050
39119
|
socket.destroy();
|
|
39051
39120
|
resolve3(true);
|
|
39052
39121
|
});
|
|
@@ -39103,14 +39172,14 @@ function parseFleetPluginManifest(value) {
|
|
|
39103
39172
|
};
|
|
39104
39173
|
}
|
|
39105
39174
|
function discoverPluginRoot(root, builtInDistRoot, external) {
|
|
39106
|
-
if (!
|
|
39107
|
-
const entries =
|
|
39175
|
+
if (!fs10__default.existsSync(root)) return [];
|
|
39176
|
+
const entries = fs10__default.readdirSync(root, { withFileTypes: true });
|
|
39108
39177
|
const plugins = [];
|
|
39109
39178
|
for (const entry of entries) {
|
|
39110
39179
|
if (!entry.isDirectory() || entry.name === "shared") continue;
|
|
39111
39180
|
const pluginRoot = path18__default.join(root, entry.name);
|
|
39112
39181
|
const manifestPath = path18__default.join(pluginRoot, "plugin.json");
|
|
39113
|
-
if (!
|
|
39182
|
+
if (!fs10__default.existsSync(manifestPath)) continue;
|
|
39114
39183
|
const manifest = readManifest(manifestPath);
|
|
39115
39184
|
if (!manifest) continue;
|
|
39116
39185
|
const clientEntry = resolveOptionalManifestEntry(pluginRoot, manifest.client, "client");
|
|
@@ -39122,14 +39191,14 @@ function discoverPluginRoot(root, builtInDistRoot, external) {
|
|
|
39122
39191
|
return plugins;
|
|
39123
39192
|
}
|
|
39124
39193
|
function discoverDistPluginRoot(root) {
|
|
39125
|
-
if (!
|
|
39126
|
-
const entries =
|
|
39194
|
+
if (!fs10__default.existsSync(root)) return [];
|
|
39195
|
+
const entries = fs10__default.readdirSync(root, { withFileTypes: true });
|
|
39127
39196
|
const plugins = [];
|
|
39128
39197
|
for (const entry of entries) {
|
|
39129
39198
|
if (!entry.isDirectory() || entry.name === "shared") continue;
|
|
39130
39199
|
const pluginRoot = path18__default.join(root, entry.name);
|
|
39131
39200
|
const manifestPath = path18__default.join(pluginRoot, "plugin.json");
|
|
39132
|
-
const manifest =
|
|
39201
|
+
const manifest = fs10__default.existsSync(manifestPath) ? readManifest(manifestPath) : readDistPluginManifest(entry.name);
|
|
39133
39202
|
if (!manifest) continue;
|
|
39134
39203
|
const clientEntry = resolveOptionalManifestEntry(pluginRoot, manifest.client, "client");
|
|
39135
39204
|
if (clientEntry === false) continue;
|
|
@@ -39141,7 +39210,7 @@ function discoverDistPluginRoot(root) {
|
|
|
39141
39210
|
}
|
|
39142
39211
|
function readManifest(manifestPath) {
|
|
39143
39212
|
try {
|
|
39144
|
-
const manifest = parseFleetPluginManifest(JSON.parse(
|
|
39213
|
+
const manifest = parseFleetPluginManifest(JSON.parse(fs10__default.readFileSync(manifestPath, "utf8")));
|
|
39145
39214
|
if (!manifest) console.warn(`[fleet-console] Plugin manifest skipped: invalid manifest at ${manifestPath}`);
|
|
39146
39215
|
return manifest;
|
|
39147
39216
|
} catch (error51) {
|
|
@@ -39156,10 +39225,10 @@ function resolveRoutesEntry(pluginRoot, manifest, builtInDistRoot) {
|
|
|
39156
39225
|
if (manifestRoute2) return manifestRoute2;
|
|
39157
39226
|
}
|
|
39158
39227
|
const manifestRoute = path18__default.join(pluginRoot, "routes.ts");
|
|
39159
|
-
if (
|
|
39228
|
+
if (fs10__default.existsSync(manifestRoute)) return manifestRoute;
|
|
39160
39229
|
if (!builtInDistRoot) return null;
|
|
39161
39230
|
const builtRoute = path18__default.join(builtInDistRoot, manifest.id, "routes.mjs");
|
|
39162
|
-
return
|
|
39231
|
+
return fs10__default.existsSync(builtRoute) ? builtRoute : null;
|
|
39163
39232
|
}
|
|
39164
39233
|
function resolveDistRoutesEntry(pluginRoot, manifest) {
|
|
39165
39234
|
const routesEntry = resolveOptionalManifestEntry(pluginRoot, manifest.routes ?? "routes.mjs", "routes");
|
|
@@ -39173,9 +39242,9 @@ function resolveOptionalManifestEntry(pluginRoot, entryPath, label) {
|
|
|
39173
39242
|
return false;
|
|
39174
39243
|
}
|
|
39175
39244
|
const candidate = path18__default.resolve(pluginRoot, entryPath);
|
|
39176
|
-
if (!
|
|
39177
|
-
const rootRealpath =
|
|
39178
|
-
const entryRealpath =
|
|
39245
|
+
if (!fs10__default.existsSync(candidate)) return null;
|
|
39246
|
+
const rootRealpath = fs10__default.realpathSync.native(pluginRoot);
|
|
39247
|
+
const entryRealpath = fs10__default.realpathSync.native(candidate);
|
|
39179
39248
|
if (!isSubpath(rootRealpath, entryRealpath)) {
|
|
39180
39249
|
console.warn(`[fleet-console] Plugin ${label} entry skipped: path escapes plugin root ${entryPath}`);
|
|
39181
39250
|
return false;
|
|
@@ -40103,7 +40172,7 @@ function tryServeStaticConsole(req, res, pathname, consoleRoot, getActiveTheme)
|
|
|
40103
40172
|
return true;
|
|
40104
40173
|
}
|
|
40105
40174
|
try {
|
|
40106
|
-
const data =
|
|
40175
|
+
const data = fs10__default.readFileSync(absolutePath);
|
|
40107
40176
|
const contentType = MIME_TYPES[path18__default.extname(absolutePath)] ?? "application/octet-stream";
|
|
40108
40177
|
res.writeHead(200, withSecurityHeaders2({ "Content-Type": contentType }));
|
|
40109
40178
|
if (req.method === "HEAD") {
|
|
@@ -40124,7 +40193,7 @@ function tryServeStaticConsole(req, res, pathname, consoleRoot, getActiveTheme)
|
|
|
40124
40193
|
}
|
|
40125
40194
|
function serveFallbackIndex(req, res, consoleRoot, getActiveTheme) {
|
|
40126
40195
|
try {
|
|
40127
|
-
const data =
|
|
40196
|
+
const data = fs10__default.readFileSync(path18__default.join(consoleRoot, "index.html"));
|
|
40128
40197
|
res.writeHead(200, withSecurityHeaders2({ "Content-Type": MIME_TYPES[".html"] }));
|
|
40129
40198
|
if (req.method === "HEAD") {
|
|
40130
40199
|
res.end();
|
|
@@ -40171,7 +40240,7 @@ function consoleUpdateProgressPath(dataDir) {
|
|
|
40171
40240
|
return path18__default.join(dataDir, CONSOLE_UPDATE_PROGRESS_FILE);
|
|
40172
40241
|
}
|
|
40173
40242
|
function readConsoleUpdateProgress(dataDir, deps = {}) {
|
|
40174
|
-
const readFile7 = deps.readFile ?? ((filePath) =>
|
|
40243
|
+
const readFile7 = deps.readFile ?? ((filePath) => fs10__default.readFileSync(filePath, "utf8"));
|
|
40175
40244
|
const now = deps.now ?? Date.now;
|
|
40176
40245
|
let raw;
|
|
40177
40246
|
try {
|
|
@@ -40231,10 +40300,10 @@ function isConsoleUpdatePhase(value) {
|
|
|
40231
40300
|
}
|
|
40232
40301
|
function writeConsoleUpdateProgress(dataDir, record4, deps = {}) {
|
|
40233
40302
|
const makeDir = deps.makeDir ?? ((dirPath, options) => {
|
|
40234
|
-
|
|
40303
|
+
fs10__default.mkdirSync(dirPath, options);
|
|
40235
40304
|
});
|
|
40236
40305
|
const writeFile5 = deps.writeFile ?? ((filePath, content, options) => {
|
|
40237
|
-
|
|
40306
|
+
fs10__default.writeFileSync(filePath, content, { mode: options.mode });
|
|
40238
40307
|
});
|
|
40239
40308
|
makeDir(dataDir, { recursive: true, mode: 448 });
|
|
40240
40309
|
writeFile5(consoleUpdateProgressPath(dataDir), JSON.stringify(record4, null, 2), { mode: PROGRESS_FILE_MODE });
|
|
@@ -40252,7 +40321,7 @@ function createConsoleUpdateApplyService(deps = {}) {
|
|
|
40252
40321
|
const childEnv = env.FLEET_CONSOLE_NO_SYSTEM_CA === "1" ? env : withNodeSystemCa(env);
|
|
40253
40322
|
const execPath = deps.execPath ?? process4.execPath;
|
|
40254
40323
|
const makeDir = deps.makeDir ?? ((dirPath, options) => {
|
|
40255
|
-
|
|
40324
|
+
fs10__default.mkdirSync(dirPath, options);
|
|
40256
40325
|
});
|
|
40257
40326
|
const now = deps.now ?? Date.now;
|
|
40258
40327
|
const processPid = deps.processPid ?? process4.pid;
|
|
@@ -40261,7 +40330,7 @@ function createConsoleUpdateApplyService(deps = {}) {
|
|
|
40261
40330
|
const spawnWorker = deps.spawnWorker ?? defaultSpawnWorker;
|
|
40262
40331
|
const tmpDir = deps.tmpDir ?? os4__default.tmpdir();
|
|
40263
40332
|
const writeFile5 = deps.writeFile ?? ((filePath, content, options) => {
|
|
40264
|
-
|
|
40333
|
+
fs10__default.writeFileSync(filePath, content, { mode: options.mode });
|
|
40265
40334
|
});
|
|
40266
40335
|
async function start(request) {
|
|
40267
40336
|
if (isManagedRuntimePackageRoot(request.currentPackageRoot)) throw new Error("managed_runtime_update_requires_relaunch");
|
|
@@ -40684,7 +40753,7 @@ function readEndpointPort(endpoint) {
|
|
|
40684
40753
|
function isManagedRuntimePackageRoot(packageRoot) {
|
|
40685
40754
|
if (path18__default.basename(packageRoot) !== "latest" || path18__default.basename(path18__default.dirname(packageRoot)) !== "console") return false;
|
|
40686
40755
|
try {
|
|
40687
|
-
return isDesktopResourceRootMarkerValid(
|
|
40756
|
+
return isDesktopResourceRootMarkerValid(fs10__default.readFileSync(path18__default.join(packageRoot, DESKTOP_RESOURCE_ROOT_MARKER), "utf8"));
|
|
40688
40757
|
} catch {
|
|
40689
40758
|
return false;
|
|
40690
40759
|
}
|
|
@@ -40735,7 +40804,7 @@ function defaultSpawnWorker(execPath, args, options) {
|
|
|
40735
40804
|
}
|
|
40736
40805
|
function resolveDefaultServerModulePath() {
|
|
40737
40806
|
const builtPath = fileURLToPath(new URL("../dist/cli.mjs", import.meta.url));
|
|
40738
|
-
if (
|
|
40807
|
+
if (fs10__default.existsSync(builtPath)) return builtPath;
|
|
40739
40808
|
const sourcePath = fileURLToPath(import.meta.url);
|
|
40740
40809
|
if (sourcePath.endsWith(".ts")) {
|
|
40741
40810
|
return sourcePath.replace(/update-apply\.ts$/, "cli.ts");
|
|
@@ -41181,8 +41250,8 @@ function createConsoleServer(deps = {}) {
|
|
|
41181
41250
|
unregisterTheaterWorkspaces: (theaterId) => codex.unregisterTheaterWorkspaces(theaterId),
|
|
41182
41251
|
validateTheaterRestore: async (theater) => {
|
|
41183
41252
|
try {
|
|
41184
|
-
const restoredRealpath = await
|
|
41185
|
-
const stat4 = await
|
|
41253
|
+
const restoredRealpath = await fs10__default.promises.realpath(theater.path);
|
|
41254
|
+
const stat4 = await fs10__default.promises.stat(restoredRealpath);
|
|
41186
41255
|
if (!stat4.isDirectory() || restoredRealpath !== theater.realpath || workspaceHash(restoredRealpath) !== theater.id) {
|
|
41187
41256
|
throw new Error("restore_conflict");
|
|
41188
41257
|
}
|
|
@@ -42972,7 +43041,7 @@ function resolveBuiltInPluginDiscoveryRoots(packageRoot) {
|
|
|
42972
43041
|
const packageRootRepo = path18__default.resolve(packageRoot, "..", "..");
|
|
42973
43042
|
const sourceRoot = path18__default.join(packageRootRepo, "runtime", "fleet-plugins");
|
|
42974
43043
|
return {
|
|
42975
|
-
...
|
|
43044
|
+
...fs10__default.existsSync(sourceRoot) ? { builtInSourceRoot: sourceRoot } : {},
|
|
42976
43045
|
builtInDistRoot: path18__default.join(packageRoot, "dist", "fleet-plugins")
|
|
42977
43046
|
};
|
|
42978
43047
|
}
|
|
@@ -43171,7 +43240,7 @@ function isAllowedTerminalOrigin(req, expectedOrigin) {
|
|
|
43171
43240
|
async function readPluginStorageJson(dataDir, pluginId, key) {
|
|
43172
43241
|
const file2 = resolvePluginStorageFile(dataDir, pluginId, key);
|
|
43173
43242
|
try {
|
|
43174
|
-
return JSON.parse(await
|
|
43243
|
+
return JSON.parse(await fs10__default.promises.readFile(file2, "utf8"));
|
|
43175
43244
|
} catch (error51) {
|
|
43176
43245
|
if (isNodeError(error51) && error51.code === "ENOENT") return null;
|
|
43177
43246
|
throw error51;
|
|
@@ -43179,8 +43248,8 @@ async function readPluginStorageJson(dataDir, pluginId, key) {
|
|
|
43179
43248
|
}
|
|
43180
43249
|
async function writePluginStorageJson(dataDir, pluginId, key, value) {
|
|
43181
43250
|
const file2 = resolvePluginStorageFile(dataDir, pluginId, key);
|
|
43182
|
-
await
|
|
43183
|
-
await
|
|
43251
|
+
await fs10__default.promises.mkdir(path18__default.dirname(file2), { recursive: true });
|
|
43252
|
+
await fs10__default.promises.writeFile(file2, JSON.stringify(value), "utf8");
|
|
43184
43253
|
}
|
|
43185
43254
|
function resolvePluginStorageFile(dataDir, pluginId, key) {
|
|
43186
43255
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(pluginId) || !/^[a-z0-9][a-z0-9._-]*$/i.test(key)) {
|
|
@@ -43191,18 +43260,6 @@ function resolvePluginStorageFile(dataDir, pluginId, key) {
|
|
|
43191
43260
|
function isNodeError(error51) {
|
|
43192
43261
|
return error51 instanceof Error && "code" in error51;
|
|
43193
43262
|
}
|
|
43194
|
-
function createConsoleStalePolicy(deps = {}) {
|
|
43195
|
-
const fsImpl = deps.fs ?? fs9__default;
|
|
43196
|
-
function isBuildStale(lock, buildFile) {
|
|
43197
|
-
try {
|
|
43198
|
-
return lock.startedAt < fsImpl.statSync(buildFile).mtimeMs;
|
|
43199
|
-
} catch (err) {
|
|
43200
|
-
if (err.code === "ENOENT") return false;
|
|
43201
|
-
throw err;
|
|
43202
|
-
}
|
|
43203
|
-
}
|
|
43204
|
-
return { isBuildStale };
|
|
43205
|
-
}
|
|
43206
43263
|
|
|
43207
43264
|
// core/host/console-lifecycle.ts
|
|
43208
43265
|
var FIXED_HOST = "127.0.0.1";
|
|
@@ -43497,7 +43554,7 @@ ${await runConsoleStatus()}
|
|
|
43497
43554
|
}
|
|
43498
43555
|
function resolveDefaultServerModulePath2() {
|
|
43499
43556
|
const builtPath = new URL("../dist/cli.mjs", import.meta.url).pathname;
|
|
43500
|
-
if (
|
|
43557
|
+
if (fs10__default.existsSync(builtPath)) return builtPath;
|
|
43501
43558
|
return fileURLToPath(import.meta.url);
|
|
43502
43559
|
}
|
|
43503
43560
|
function readHookSessionId(env) {
|
|
@@ -43556,7 +43613,7 @@ function readStdinBestEffort() {
|
|
|
43556
43613
|
function isCliDirectRun(argv1, moduleUrl = import.meta.url) {
|
|
43557
43614
|
if (!argv1) return false;
|
|
43558
43615
|
try {
|
|
43559
|
-
return
|
|
43616
|
+
return fs10__default.realpathSync(path18__default.resolve(argv1)) === fs10__default.realpathSync(fileURLToPath(moduleUrl));
|
|
43560
43617
|
} catch {
|
|
43561
43618
|
return false;
|
|
43562
43619
|
}
|