@mnemonik/cli 7.109.3 → 7.110.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.
Files changed (104) hide show
  1. package/dist/auth/credentials.js +297 -36
  2. package/dist/auth/index.d.ts +2 -0
  3. package/dist/auth/index.d.ts.map +1 -1
  4. package/dist/auth/index.js +1914 -19
  5. package/dist/auth/index.js.map +1 -1
  6. package/dist/auth/machineName.d.ts +8 -0
  7. package/dist/auth/machineName.d.ts.map +1 -0
  8. package/dist/auth/machineName.js +23 -0
  9. package/dist/auth/machineName.js.map +1 -0
  10. package/dist/consent.d.ts +29 -0
  11. package/dist/consent.d.ts.map +1 -0
  12. package/dist/consent.js +87 -0
  13. package/dist/consent.js.map +1 -0
  14. package/dist/diagnostics.js +301 -40
  15. package/dist/digests.json +102 -90
  16. package/dist/help.d.ts.map +1 -1
  17. package/dist/help.js +59 -44
  18. package/dist/help.js.map +1 -1
  19. package/dist/humanReason.d.ts +8 -0
  20. package/dist/humanReason.d.ts.map +1 -1
  21. package/dist/humanReason.js +44 -16
  22. package/dist/humanReason.js.map +1 -1
  23. package/dist/identity/migrate.js +1835 -44
  24. package/dist/install/hosts.d.ts +2 -0
  25. package/dist/install/hosts.d.ts.map +1 -1
  26. package/dist/install/hosts.js +23 -14
  27. package/dist/install/hosts.js.map +1 -1
  28. package/dist/install/journal.js +124 -11
  29. package/dist/install/journey.d.ts +20 -0
  30. package/dist/install/journey.d.ts.map +1 -1
  31. package/dist/install/journey.js +1913 -82
  32. package/dist/install/journey.js.map +1 -1
  33. package/dist/install/ownership.d.ts.map +1 -1
  34. package/dist/install/ownership.js +1818 -10
  35. package/dist/install/ownership.js.map +1 -1
  36. package/dist/install/transaction.js +1913 -19
  37. package/dist/install/ui.js +1910 -15
  38. package/dist/installation.js +133 -10
  39. package/dist/launcher.js +108 -4
  40. package/dist/output.d.ts +3 -0
  41. package/dist/output.d.ts.map +1 -1
  42. package/dist/output.js +11 -1
  43. package/dist/output.js.map +1 -1
  44. package/dist/preflight.d.ts +5 -0
  45. package/dist/preflight.d.ts.map +1 -1
  46. package/dist/preflight.js +14 -12
  47. package/dist/preflight.js.map +1 -1
  48. package/dist/project/eligibility.js +1917 -22
  49. package/dist/project/records.js +121 -8
  50. package/dist/project.d.ts +15 -0
  51. package/dist/project.d.ts.map +1 -1
  52. package/dist/project.js +229 -15
  53. package/dist/project.js.map +1 -1
  54. package/dist/router.d.ts +2 -0
  55. package/dist/router.d.ts.map +1 -1
  56. package/dist/router.js +2164 -122
  57. package/dist/router.js.map +1 -1
  58. package/dist/runtime/releaseSource.d.ts +6 -0
  59. package/dist/runtime/releaseSource.d.ts.map +1 -1
  60. package/dist/runtime/releaseSource.js +1933 -32
  61. package/dist/runtime/releaseSource.js.map +1 -1
  62. package/dist/runtime/selfUpdate.js +1809 -8
  63. package/dist/runtime/signers.js +28 -9
  64. package/dist/runtime/store.js +18 -6
  65. package/dist/runtime/updateCheck.d.ts +4 -0
  66. package/dist/runtime/updateCheck.d.ts.map +1 -0
  67. package/dist/runtime/updateCheck.js +6695 -0
  68. package/dist/runtime/updateCheck.js.map +1 -0
  69. package/dist/sbom.json +21 -21
  70. package/dist/scanner/control.d.ts +27 -1
  71. package/dist/scanner/control.d.ts.map +1 -1
  72. package/dist/scanner/control.js +207 -36
  73. package/dist/scanner/control.js.map +1 -1
  74. package/dist/scanner/discover.d.ts +5 -0
  75. package/dist/scanner/discover.d.ts.map +1 -1
  76. package/dist/scanner/discover.js +16 -6
  77. package/dist/scanner/discover.js.map +1 -1
  78. package/dist/scanner/enable.d.ts +2 -0
  79. package/dist/scanner/enable.d.ts.map +1 -1
  80. package/dist/scanner/enable.js +152 -14
  81. package/dist/scanner/enable.js.map +1 -1
  82. package/dist/scanner/picker.d.ts.map +1 -1
  83. package/dist/scanner/picker.js +5 -6
  84. package/dist/scanner/picker.js.map +1 -1
  85. package/dist/scanner/service.d.ts +2 -0
  86. package/dist/scanner/service.d.ts.map +1 -1
  87. package/dist/scanner/service.js +279 -54
  88. package/dist/scanner/service.js.map +1 -1
  89. package/dist/scanner/update.d.ts +8 -0
  90. package/dist/scanner/update.d.ts.map +1 -1
  91. package/dist/scanner/update.js +254 -20
  92. package/dist/scanner/update.js.map +1 -1
  93. package/dist/scanner-release.json +35 -30
  94. package/dist/screens/journey.d.ts +6 -1
  95. package/dist/screens/journey.d.ts.map +1 -1
  96. package/dist/screens/journey.js +29 -8
  97. package/dist/screens/journey.js.map +1 -1
  98. package/dist/status.d.ts +21 -0
  99. package/dist/status.d.ts.map +1 -1
  100. package/dist/status.js +1993 -39
  101. package/dist/status.js.map +1 -1
  102. package/dist/vendor/local-setup.js +256 -29
  103. package/dist/vendor/shared/runtimeSigners.js +38 -11
  104. package/package.json +31 -31
@@ -502,7 +502,9 @@ var require_ignore = __commonJS({
502
502
  });
503
503
 
504
504
  // packages/shared/dist/runtimeSigners.js
505
+ import { lstatSync, mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync } from "node:fs";
505
506
  import { basename, dirname as dirname2, join as join2, resolve, sep, win32 } from "node:path";
507
+ import { createHash, createPublicKey, randomUUID, timingSafeEqual, verify as verifySignature } from "node:crypto";
506
508
  import { execFile, execFileSync } from "node:child_process";
507
509
  function windowsCommand(file) {
508
510
  const root = process.env.SystemRoot;
@@ -510,14 +512,44 @@ function windowsCommand(file) {
510
512
  throw new Error("acl_system_root_unavailable");
511
513
  return win32.join(root, "System32", file);
512
514
  }
513
- function readIdentity(stdout) {
514
- const match = /^"([^"\r\n]+)","(S-1-(?:\d+-)+\d+)"$/.exec(stdout.trim());
515
- if (!match?.[1] || !match[2] || stdout.includes("\uFFFD"))
515
+ function readIdentity(stdout2) {
516
+ const match = /^"([^"\r\n]+)","(S-1-(?:\d+-)+\d+)"$/.exec(stdout2.trim());
517
+ if (!match?.[1] || !match[2] || stdout2.includes("\uFFFD"))
516
518
  throw new Error("acl_identity_unavailable");
517
519
  return { name: match[1], sid: match[2] };
518
520
  }
521
+ function* readWindowsIdentity() {
522
+ const user = readIdentity(yield [windowsCommand("whoami.exe"), identityArgs]);
523
+ if (!ADMINISTRATOR_RID.test(user.sid))
524
+ return user;
525
+ const groups = yield [windowsCommand("whoami.exe"), groupArgs];
526
+ const local = /^"[^"\r\n]*","[^"\r\n]*","S-1-5-113",/m.test(groups);
527
+ return {
528
+ ...user,
529
+ localAdministratorSid: local ? `${user.sid.slice(0, user.sid.lastIndexOf("-"))}-500` : null
530
+ };
531
+ }
519
532
  function windowsCurrentAccountSync() {
520
- return currentIdentity ??= readIdentity(hookExecuteSync(windowsCommand("whoami.exe"), identityArgs));
533
+ if (currentIdentity)
534
+ return currentIdentity;
535
+ const commands = readWindowsIdentity();
536
+ let step = commands.next();
537
+ while (!step.done)
538
+ step = commands.next(hookExecuteSync(...step.value));
539
+ return currentIdentity = step.value;
540
+ }
541
+ async function windowsIdentity(run2) {
542
+ if (currentIdentity)
543
+ return currentIdentity;
544
+ identityPending ??= drive(readWindowsIdentity(), run2).then((identity) => currentIdentity = identity).finally(() => {
545
+ identityPending = void 0;
546
+ });
547
+ return identityPending;
548
+ }
549
+ async function verifyWindowsAcl(path, run2 = hookExecute, state) {
550
+ const user = await windowsIdentity(run2);
551
+ if (!privateEntries((await drive(saveAcl(path, false, [path], state), run2)).get(path), user, false))
552
+ throw new Error("acl_permissions");
521
553
  }
522
554
  function hookInvocation(file, args2) {
523
555
  if (win32.basename(file) === "whoami.exe") {
@@ -537,12 +569,112 @@ function hookExecuteSync(file, args2, input) {
537
569
  [file, args2] = hookInvocation(file, args2);
538
570
  return execFileSync(file, args2, { ...hookOptions(file, args2), input });
539
571
  }
540
- var identityArgs, currentIdentity, ttl, hookOptions;
572
+ function aclRecords(output, root, paths, onLookup) {
573
+ const records = /* @__PURE__ */ new Map();
574
+ const wanted = new Set(paths);
575
+ const lines = output.replace(/^\uFEFF/, "").trimEnd().split(/\r?\n/);
576
+ if (lines.length % 2)
577
+ throw new Error("acl_unavailable");
578
+ for (let index = 0; index < lines.length; index += 2) {
579
+ onLookup?.();
580
+ const relativePath = lines[index];
581
+ const descriptor = lines[index + 1];
582
+ if (relativePath === void 0 || descriptor === void 0)
583
+ throw new Error("acl_unavailable");
584
+ const path = resolve(dirname2(root), relativePath.replaceAll("\\", sep));
585
+ if (!wanted.has(path))
586
+ continue;
587
+ if (records.has(path))
588
+ throw new Error("acl_unavailable");
589
+ const dacl = /^D:(?:P|AI|AR)*((?:\([^()]*\))*)$/.exec(descriptor);
590
+ records.set(path, dacl?.[1]?.match(/\([^()]*\)/g) ?? []);
591
+ }
592
+ return records;
593
+ }
594
+ function privateEntries(entries, user, directory) {
595
+ if (!entries?.length)
596
+ throw new Error("acl_unavailable");
597
+ return entries.every((line) => {
598
+ const ace = /^\(([AD]);((?:OI|CI|NP|IO|ID|SA|FA)*);[A-Za-z0-9]+;;;((?:S-1-(?:\d+-)+\d+)|[A-Z]{2})\)$/.exec(line);
599
+ if (!ace)
600
+ throw new Error("acl_unavailable");
601
+ const sid = ace[3] === "LA" ? user.localAdministratorSid : ace[3];
602
+ return (!directory || !ace[2]?.includes("ID")) && (ace[1] === "D" || sid === user.sid);
603
+ });
604
+ }
605
+ function* prepareAclDirectory(state) {
606
+ const directory = join2(state, "audit-tmp");
607
+ if (auditDirectories.has(directory)) {
608
+ const stat2 = lstatSync(directory);
609
+ if (!stat2.isDirectory() || stat2.isSymbolicLink())
610
+ throw new Error("acl_permissions");
611
+ return directory;
612
+ }
613
+ let created = false;
614
+ try {
615
+ mkdirSync(directory, { mode: 448 });
616
+ created = true;
617
+ } catch (error) {
618
+ if (error.code !== "EEXIST")
619
+ throw error;
620
+ }
621
+ const stat = lstatSync(directory);
622
+ if (!stat.isDirectory() || stat.isSymbolicLink())
623
+ throw new Error("acl_permissions");
624
+ if (!auditDirectories.has(directory)) {
625
+ currentIdentity ??= yield* readWindowsIdentity();
626
+ yield [windowsCommand("icacls.exe"), aclArgs(directory, currentIdentity.sid, created)];
627
+ if (!created) {
628
+ const temp = join2(directory, `.acl-${randomUUID()}.tmp`);
629
+ writeFileSync(temp, "", { flag: "wx", mode: 384 });
630
+ try {
631
+ yield [windowsCommand("icacls.exe"), [directory, "/save", temp, "/l"]];
632
+ if (!privateEntries(aclRecords(readFileSync(temp, "utf16le"), directory, [directory]).get(directory), currentIdentity, true))
633
+ throw new Error("acl_permissions");
634
+ } finally {
635
+ unlinkSync(temp);
636
+ }
637
+ }
638
+ auditDirectories.add(directory);
639
+ }
640
+ return directory;
641
+ }
642
+ function* saveAcl(path, recursive, paths = [path], state = lstatSync(path).isDirectory() ? path : dirname2(path)) {
643
+ const directory = yield* prepareAclDirectory(state);
644
+ const temp = join2(directory, `.acl-${randomUUID()}.tmp`);
645
+ writeFileSync(temp, "", { flag: "wx", mode: 384 });
646
+ try {
647
+ yield [windowsCommand("icacls.exe"), [path, "/save", temp, ...recursive ? ["/t"] : [], "/l"]];
648
+ return aclRecords(readFileSync(temp, "utf16le"), path, paths.filter((item) => item !== directory && !item.startsWith(directory + sep)));
649
+ } finally {
650
+ unlinkSync(temp);
651
+ }
652
+ }
653
+ async function drive(commands, run2) {
654
+ try {
655
+ let step = commands.next();
656
+ while (!step.done)
657
+ step = commands.next(stdout(await run2(...step.value)));
658
+ return step.value;
659
+ } finally {
660
+ commands.return(void 0);
661
+ }
662
+ }
663
+ var identityArgs, groupArgs, ADMINISTRATOR_RID, currentIdentity, ttl, identityPending, aclArgs, hookOptions, hookExecute, stdout, auditDirectories;
541
664
  var init_runtimeSigners = __esm({
542
665
  "packages/shared/dist/runtimeSigners.js"() {
543
666
  "use strict";
544
667
  identityArgs = ["/user", "/fo", "csv", "/nh"];
668
+ groupArgs = ["/groups", "/fo", "csv", "/nh"];
669
+ ADMINISTRATOR_RID = /^S-1-5-21-\d+-\d+-\d+-500$/;
545
670
  ttl = 10 * 6e4;
671
+ aclArgs = (path, sid, created = false) => [
672
+ path,
673
+ "/inheritance:r",
674
+ "/grant:r",
675
+ `*${sid}:(OI)(CI)F`,
676
+ ...created ? ["/remove:g", "*S-1-5-32-544", "*S-1-5-18"] : []
677
+ ];
546
678
  hookOptions = (file, args2) => ({
547
679
  encoding: args2.includes("/u") ? "utf16le" : "utf8",
548
680
  timeout: win32.basename(file) === "powershell.exe" ? 3e4 : 5e3,
@@ -550,6 +682,22 @@ var init_runtimeSigners = __esm({
550
682
  maxBuffer: 16 * 1024 * 1024,
551
683
  windowsVerbatimArguments: win32.basename(file) === "cmd.exe"
552
684
  });
685
+ hookExecute = (file, args2, input) => {
686
+ const treeListing = win32.basename(file) === "icacls.exe" && args2.includes("/t") || win32.basename(file) === "cmd.exe" && args2.some((arg) => arg.startsWith("dir /q /a /s "));
687
+ [file, args2] = hookInvocation(file, args2);
688
+ const options = hookOptions(file, args2);
689
+ if (treeListing)
690
+ options.timeout = 3e4;
691
+ return new Promise((resolve3, reject) => {
692
+ const child = execFile(file, args2, options, (error, stdout2) => error ? reject(error) : resolve3({ stdout: stdout2 }));
693
+ if (input !== void 0) {
694
+ child.stdin?.on("error", reject);
695
+ child.stdin?.end(input);
696
+ }
697
+ });
698
+ };
699
+ stdout = (value) => value.stdout;
700
+ auditDirectories = /* @__PURE__ */ new Set();
553
701
  }
554
702
  });
555
703
 
@@ -2198,7 +2346,7 @@ var require_proper_lockfile = __commonJS({
2198
2346
 
2199
2347
  // packages/credentials/dist/index.js
2200
2348
  import { createHmac, randomBytes } from "node:crypto";
2201
- import { join as join5 } from "node:path";
2349
+ import { join as join6 } from "node:path";
2202
2350
 
2203
2351
  // packages/shared/dist/instructions.js
2204
2352
  var INSTRUCTIONS_CONTENT = `Mnemonik provides persistent project memory: decisions, rationale, tasks, and policies across sessions. If no block begins "PROJECT_CONTEXT schemaVersion=", session_bootstrap({ cwd }) loads project context when cwd is the real absolute path of the project root; a placeholder or relative path fails. With that block, context is loaded and no session_bootstrap call is needed. Code and docs show current artifacts, git shows changes, and memory carries the why; memory_search recalls rationale or intent, then Grep or Read verifies current source.
@@ -6393,7 +6541,7 @@ init_repositoryRoot();
6393
6541
  // packages/local-setup/dist/storage.js
6394
6542
  init_hookRuntime();
6395
6543
  init_hookRuntime();
6396
- import { createHash, randomUUID } from "node:crypto";
6544
+ import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
6397
6545
  import { execFile as nodeExecFile } from "node:child_process";
6398
6546
  import fs2 from "node:fs";
6399
6547
  import { open, rename, readFile, mkdir, lstat, chmod, writeFile, unlink, rmdir } from "node:fs/promises";
@@ -6456,6 +6604,9 @@ async function windowsCurrentUserAcl(path, directory = false, options = {}, crea
6456
6604
  });
6457
6605
  });
6458
6606
  }
6607
+ async function verifyWindowsCurrentUserOnly(path, state, run2) {
6608
+ await verifyWindowsAcl(path, run2, state);
6609
+ }
6459
6610
  async function protectStateFile(path, platform = process.platform, aclOptions) {
6460
6611
  if (platform === "win32")
6461
6612
  await windowsCurrentUserAcl(path, false, aclOptions);
@@ -6465,7 +6616,7 @@ async function protectStateFile(path, platform = process.platform, aclOptions) {
6465
6616
  }
6466
6617
  async function atomicWrite(path, bytes, fault, assertOwned) {
6467
6618
  await assertOwned?.();
6468
- const temp = `${path}.${randomUUID()}.tmp`;
6619
+ const temp = `${path}.${randomUUID2()}.tmp`;
6469
6620
  const fd = await open(temp, "wx", 384);
6470
6621
  let permissionStatus;
6471
6622
  try {
@@ -6487,7 +6638,7 @@ async function atomicWrite(path, bytes, fault, assertOwned) {
6487
6638
  async function withLock(path, waitMs, work) {
6488
6639
  const lockfile = await sharedLockfile();
6489
6640
  await mkdir(dirname3(path), { recursive: true, mode: 448 });
6490
- const generation = randomUUID();
6641
+ const generation = randomUUID2();
6491
6642
  const owner = join3(`${path}.lock`, "owner");
6492
6643
  let compromised = false;
6493
6644
  let acquired = false;
@@ -6552,6 +6703,100 @@ async function withLock(path, waitMs, work) {
6552
6703
  }
6553
6704
  }
6554
6705
 
6706
+ // packages/local-setup/dist/automaticUpdate.js
6707
+ import { spawn as nodeSpawn } from "node:child_process";
6708
+ import { realpathSync } from "node:fs";
6709
+ import { stat as nodeStat, utimes } from "node:fs/promises";
6710
+ import { homedir as homedir2 } from "node:os";
6711
+ import { join as join4 } from "node:path";
6712
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
6713
+ var DAY_MS = 864e5;
6714
+ var statePath = (stateDir) => join4(stateDir, "automatic-update.json");
6715
+ function cliLauncherPath(options = {}) {
6716
+ const platform = options.platform ?? process.platform;
6717
+ const home = options.home ?? homedir2();
6718
+ return platform === "win32" ? join4(options.env?.LOCALAPPDATA || join4(home, "AppData", "Local"), "Mnemonik", "bin", "mnemonik.cmd") : join4(home, ".local", "bin", "mnemonik");
6719
+ }
6720
+ async function readState(path) {
6721
+ const bytes = await readBytes(path);
6722
+ if (!bytes)
6723
+ return {};
6724
+ const value = JSON.parse(bytes.toString());
6725
+ if (!value || typeof value !== "object" || value.lastAttempt !== void 0 && (!Number.isFinite(value.lastAttempt) || value.lastAttempt < 0))
6726
+ throw new Error("automatic_update_state_invalid");
6727
+ return value.lastAttempt === void 0 ? {} : { lastAttempt: value.lastAttempt };
6728
+ }
6729
+ async function maybeStartAutomaticUpdate(options = {}) {
6730
+ const stateDir = options.stateDir ?? stateDirectory(options.platform, options.env, options.home);
6731
+ const path = statePath(stateDir);
6732
+ try {
6733
+ const now = (options.now ?? Date.now)();
6734
+ const stat = options.stat ?? nodeStat;
6735
+ try {
6736
+ if (now - (await stat(path)).mtimeMs < DAY_MS)
6737
+ return false;
6738
+ } catch (error) {
6739
+ if (error.code !== "ENOENT")
6740
+ throw error;
6741
+ }
6742
+ if (!options.spawn && !(await stat(cliLauncherPath(options))).isFile())
6743
+ return false;
6744
+ return await withLock(path, 0, async (assertOwned) => {
6745
+ const state = await readState(path);
6746
+ if (state.lastAttempt !== void 0 && now - state.lastAttempt < DAY_MS)
6747
+ return false;
6748
+ await atomicWrite(path, Buffer.from(`${JSON.stringify({ lastAttempt: now })}
6749
+ `), void 0, assertOwned);
6750
+ await utimes(path, now / 1e3, now / 1e3);
6751
+ const platform = options.platform ?? process.platform;
6752
+ const launcher = cliLauncherPath(options);
6753
+ const command = platform === "win32" ? {
6754
+ file: options.env?.ComSpec || "cmd.exe",
6755
+ args: ["/d", "/s", "/c", `""${launcher}" update --automatic"`],
6756
+ windowsVerbatimArguments: true
6757
+ } : platform === "linux" && (options.env ?? process.env).INVOCATION_ID ? {
6758
+ // detached creates a process group, not a new systemd cgroup. An
6759
+ // updater spawned by the scanner must survive stopping that service.
6760
+ file: "systemd-run",
6761
+ args: [
6762
+ "--user",
6763
+ "--collect",
6764
+ "--quiet",
6765
+ `--setenv=MNEMONIK_STATE_DIR=${stateDir}`,
6766
+ "--",
6767
+ launcher,
6768
+ "update",
6769
+ "--automatic"
6770
+ ]
6771
+ } : { file: launcher, args: ["update", "--automatic"] };
6772
+ const child = (options.spawn ?? nodeSpawn)(command.file, command.args, {
6773
+ detached: true,
6774
+ stdio: "ignore",
6775
+ windowsHide: true,
6776
+ ..."windowsVerbatimArguments" in command ? { windowsVerbatimArguments: command.windowsVerbatimArguments } : {}
6777
+ });
6778
+ child.once("error", () => {
6779
+ });
6780
+ child.unref();
6781
+ return true;
6782
+ });
6783
+ } catch {
6784
+ return false;
6785
+ }
6786
+ }
6787
+ var HELPER_FLAG = "--mnemonik-automatic-update";
6788
+ function isHelperInvocation() {
6789
+ if (process.argv[2] !== HELPER_FLAG || !process.argv[3] || !process.argv[1])
6790
+ return false;
6791
+ try {
6792
+ return realpathSync(process.argv[1]) === realpathSync(fileURLToPath2(import.meta.url));
6793
+ } catch {
6794
+ return false;
6795
+ }
6796
+ }
6797
+ if (isHelperInvocation())
6798
+ void maybeStartAutomaticUpdate({ stateDir: process.argv[3] });
6799
+
6555
6800
  // packages/local-setup/dist/index.js
6556
6801
  var MAX_ORIGINAL_BYTES = 64 * 1024;
6557
6802
 
@@ -6570,10 +6815,10 @@ function isCredentialSessionUnavailableError(error) {
6570
6815
  }
6571
6816
 
6572
6817
  // packages/credentials/dist/storage.js
6573
- import { createHash as createHash2 } from "node:crypto";
6818
+ import { createHash as createHash3 } from "node:crypto";
6574
6819
  import { lstat as nodeLstat, mkdir as mkdir2, open as open2, readdir, rmdir as rmdir2, unlink as unlink2 } from "node:fs/promises";
6575
6820
  import { constants } from "node:fs";
6576
- import { basename as basename2, dirname as dirname4, isAbsolute, join as join4, parse, relative, resolve as resolve2, sep as sep2 } from "node:path";
6821
+ import { basename as basename2, dirname as dirname4, isAbsolute, join as join5, parse, relative, resolve as resolve2, sep as sep2 } from "node:path";
6577
6822
  var CredentialError = class extends Error {
6578
6823
  reason;
6579
6824
  constructor(reason) {
@@ -6582,22 +6827,22 @@ var CredentialError = class extends Error {
6582
6827
  this.name = "CredentialError";
6583
6828
  }
6584
6829
  };
6585
- var digest = (value) => createHash2("sha256").update(value).digest("hex");
6830
+ var digest = (value) => createHash3("sha256").update(value).digest("hex");
6586
6831
  function credentialPaths(stateDir = stateDirectory(), familyId) {
6587
- const root = join4(stateDir, "credentials");
6832
+ const root = join5(stateDir, "credentials");
6588
6833
  const familyName = familyId ? digest(familyId) : "";
6589
6834
  return {
6590
6835
  root,
6591
- records: join4(root, "records"),
6592
- secrets: join4(root, "secrets"),
6593
- cliRecord: join4(root, "records", "cli.json"),
6594
- cliSecret: join4(root, "secrets", "cli.json"),
6595
- rootRecord: join4(root, "records", "root-binding.json"),
6596
- rootSecret: join4(root, "secrets", "root-binding.key"),
6597
- familyRecords: join4(root, "records", "families"),
6598
- familySecrets: join4(root, "secrets", "families"),
6599
- record: join4(root, "records", "families", `${familyName}.json`),
6600
- secret: join4(root, "secrets", "families", `${familyName}.json`)
6836
+ records: join5(root, "records"),
6837
+ secrets: join5(root, "secrets"),
6838
+ cliRecord: join5(root, "records", "cli.json"),
6839
+ cliSecret: join5(root, "secrets", "cli.json"),
6840
+ rootRecord: join5(root, "records", "root-binding.json"),
6841
+ rootSecret: join5(root, "secrets", "root-binding.key"),
6842
+ familyRecords: join5(root, "records", "families"),
6843
+ familySecrets: join5(root, "secrets", "families"),
6844
+ record: join5(root, "records", "families", `${familyName}.json`),
6845
+ secret: join5(root, "secrets", "families", `${familyName}.json`)
6601
6846
  };
6602
6847
  }
6603
6848
  var codeIs2 = (error, code) => error.code === code;
@@ -6609,6 +6854,7 @@ var SecureFiles = class {
6609
6854
  fault;
6610
6855
  execFile;
6611
6856
  username;
6857
+ aclRun;
6612
6858
  constructor(options = {}) {
6613
6859
  this.stateDir = resolve2(options.stateDir ?? stateDirectory());
6614
6860
  this.platform = options.platform ?? process.platform;
@@ -6617,6 +6863,7 @@ var SecureFiles = class {
6617
6863
  this.fault = options.fault;
6618
6864
  this.execFile = options.execFile;
6619
6865
  this.username = options.username;
6866
+ this.aclRun = options.aclRun;
6620
6867
  }
6621
6868
  assertInsideState(path) {
6622
6869
  const absolute = resolve2(path);
@@ -6632,7 +6879,7 @@ var SecureFiles = class {
6632
6879
  const result = [];
6633
6880
  let current2 = root;
6634
6881
  for (const part of parts2) {
6635
- current2 = join4(current2, part);
6882
+ current2 = join5(current2, part);
6636
6883
  result.push(current2);
6637
6884
  }
6638
6885
  return result;
@@ -6651,20 +6898,34 @@ var SecureFiles = class {
6651
6898
  if (value.isSymbolicLink())
6652
6899
  throw new CredentialError("symlink_rejected");
6653
6900
  const protectedComponent = component === this.stateDir || component.startsWith(`${this.stateDir}${sep2}`);
6654
- if (!protectedComponent || this.platform === "win32")
6901
+ if (!protectedComponent)
6655
6902
  continue;
6656
- if (this.uid !== void 0 && value.uid !== this.uid)
6657
- throw new CredentialError("wrong_owner");
6658
6903
  const final = component === absolute;
6659
- const allowed = final && expectFile ? 384 : 448;
6660
- if ((value.mode & 511 & ~allowed) !== 0)
6661
- throw new CredentialError("weak_permissions");
6904
+ if (this.platform === "win32") {
6905
+ if (final)
6906
+ await this.verifyWindowsPrivate(component);
6907
+ } else {
6908
+ if (this.uid !== void 0 && value.uid !== this.uid)
6909
+ throw new CredentialError("wrong_owner");
6910
+ const allowed = final && expectFile ? 384 : 448;
6911
+ if ((value.mode & 511 & ~allowed) !== 0)
6912
+ throw new CredentialError("weak_permissions");
6913
+ }
6662
6914
  if (final && expectFile && !value.isFile())
6663
6915
  throw new CredentialError("not_regular_file");
6664
6916
  if (final && !expectFile && !value.isDirectory())
6665
6917
  throw new CredentialError("not_regular_file");
6666
6918
  }
6667
6919
  }
6920
+ async verifyWindowsPrivate(path) {
6921
+ try {
6922
+ await verifyWindowsCurrentUserOnly(path, this.stateDir, this.aclRun);
6923
+ } catch (error) {
6924
+ if (error.message === "acl_permissions")
6925
+ throw new CredentialError("weak_permissions");
6926
+ throw error;
6927
+ }
6928
+ }
6668
6929
  async makeDirectory(path) {
6669
6930
  let created = false;
6670
6931
  try {
@@ -6718,7 +6979,7 @@ var SecureFiles = class {
6718
6979
  const prefix = `${basename2(absolute)}.`;
6719
6980
  for (const name2 of await this.list(dirname4(absolute))) {
6720
6981
  if (name2.startsWith(prefix) && name2.endsWith(".tmp"))
6721
- await this.remove(join4(dirname4(absolute), name2));
6982
+ await this.remove(join5(dirname4(absolute), name2));
6722
6983
  }
6723
6984
  throw error;
6724
6985
  }
@@ -6765,7 +7026,7 @@ var SecureFiles = class {
6765
7026
 
6766
7027
  // packages/credentials/dist/osSecretStore.js
6767
7028
  import { execFile as nodeExecFile2 } from "node:child_process";
6768
- import { randomUUID as randomUUID2 } from "node:crypto";
7029
+ import { randomUUID as randomUUID3 } from "node:crypto";
6769
7030
  var service = "mnemonik.credentials.v1";
6770
7031
  var unavailable = () => new Error("os_store_unavailable");
6771
7032
  var cachedReads = /* @__PURE__ */ new Map();
@@ -6844,7 +7105,7 @@ function createStore(platform, execFile2) {
6844
7105
  timeout: platform === "win32" ? 6e4 : 1e4,
6845
7106
  maxBuffer: 64 * 1024,
6846
7107
  windowsHide: true
6847
- }, (error, stdout, stderr) => {
7108
+ }, (error, stdout2, stderr) => {
6848
7109
  const code = error?.code;
6849
7110
  const notFound = missing && (platform === "darwin" ? code === 44 && stderr.includes("The specified item could not be found in the keychain.") : platform === "win32" ? code === 3 : code === 1 && !stderr);
6850
7111
  if (notFound)
@@ -6852,7 +7113,7 @@ function createStore(platform, execFile2) {
6852
7113
  else if (error)
6853
7114
  fail();
6854
7115
  else
6855
- resolve3(stdout);
7116
+ resolve3(stdout2);
6856
7117
  });
6857
7118
  child.stdin?.on("error", fail);
6858
7119
  child.stdin?.end(input);
@@ -6911,7 +7172,7 @@ ${Buffer.from(secret, "utf8").toString("base64")}
6911
7172
  if (failed)
6912
7173
  return Promise.resolve(false);
6913
7174
  return availability ??= (async () => {
6914
- const probe = `${service}:probe:${randomUUID2()}`;
7175
+ const probe = `${service}:probe:${randomUUID3()}`;
6915
7176
  if (platform === "darwin") {
6916
7177
  await run2("security", ["-i"], "default-keychain -d user\n", false);
6917
7178
  await operation("set", probe, "availability-probe");
@@ -7388,7 +7649,7 @@ function createCredentialAdapter(options = {}) {
7388
7649
  const cli = await readRecord(paths.cliRecord, "cli-oauth");
7389
7650
  const componentFamilyIds = [];
7390
7651
  for (const name2 of await files.list(paths.familyRecords)) {
7391
- const recordPath2 = join5(paths.familyRecords, name2);
7652
+ const recordPath2 = join6(paths.familyRecords, name2);
7392
7653
  const record = await readRecord(recordPath2, "component");
7393
7654
  if (!record)
7394
7655
  continue;
@@ -10,6 +10,8 @@ export interface CliAuthOptions {
10
10
  env?: NodeJS.ProcessEnv;
11
11
  platform?: NodeJS.Platform;
12
12
  deviceName?: string;
13
+ /** Reads the macOS Computer Name; replaced in tests. */
14
+ computerName?: () => Promise<string>;
13
15
  print?: (line: string) => void;
14
16
  fetch?: typeof fetch;
15
17
  openBrowser?: (url: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,uBAAuB,EAE5B,KAAK,kBAAkB,EAEvB,KAAK,wBAAwB,EAE9B,MAAM,uBAAuB,CAAC;AAI/B,eAAO,MAAM,UAAU,YACrB,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,CACR,CAAC;AAIX,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;IACzD,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;CAC9C;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAMT;AAkBD,wBAAgB,aAAa,CAAC,OAAO,GAAE,cAAmB;kBAiE/B,OAAO,CAAC,kBAAkB,CAAC;wBAsErB,OAAO,CAAC,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;2BAW/C,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;kBAgBnC,OAAO,CAAC,IAAI,CAAC;EAiBvC;AAED,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,KAAK,uBAAuB,EAE5B,KAAK,kBAAkB,EAEvB,KAAK,wBAAwB,EAE9B,MAAM,uBAAuB,CAAC;AAK/B,eAAO,MAAM,UAAU,YACrB,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,CACR,CAAC;AAIX,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;IACzD,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;CAC9C;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAMT;AAkBD,wBAAgB,aAAa,CAAC,OAAO,GAAE,cAAmB;kBAmE/B,OAAO,CAAC,kBAAkB,CAAC;wBAsErB,OAAO,CAAC,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;2BAW/C,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;kBAgBnC,OAAO,CAAC,IAAI,CAAC;EAiBvC;AAED,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}