@sberpay-cli/cli-diagnostic 0.4.0-dev.4 → 0.4.0-dev.7
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/README.md +1 -1
- package/THIRD_PARTY_NOTICES.md +5494 -0
- package/build-info.json +4 -4
- package/dist/npm-entry.mjs +309 -149
- package/manifest.json +9 -7
- package/package/SHA256SUMS +6 -4
- package/package/THIRD_PARTY_NOTICES.md +5494 -0
- package/package/dist/binding-worker.mjs +131 -46
- package/package/dist/cli.mjs +260 -133
- package/package/helpers/win32-arm64/sberpay-tpm.exe +0 -0
- package/package/helpers/win32-x64/sberpay-tpm.exe +0 -0
- package/package/package.json +3 -2
- package/package.json +5 -4
package/package/dist/cli.mjs
CHANGED
|
@@ -7375,7 +7375,7 @@ import { fileURLToPath } from "node:url";
|
|
|
7375
7375
|
var NPM_PACKAGE = true ? "@sberpay-cli/cli-diagnostic" : "@sberpay-cli/cli";
|
|
7376
7376
|
var kind = true ? "release" : "dev";
|
|
7377
7377
|
var BUILD = {
|
|
7378
|
-
sourceCommit: true ? "
|
|
7378
|
+
sourceCommit: true ? "9a9b74aaa8ed8a80225fe2dd94e6205b2c99352e" : "dev",
|
|
7379
7379
|
profile: true ? "diagnostic" : "standard",
|
|
7380
7380
|
kind,
|
|
7381
7381
|
// Бандл — dist/cli.mjs в корне пакета; этот файл под tsx — packages/cli/src/core/.
|
|
@@ -7383,9 +7383,13 @@ var BUILD = {
|
|
|
7383
7383
|
};
|
|
7384
7384
|
var REINSTALL_HINT = `\u041F\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 sberpay-cli: npm i -g ${NPM_PACKAGE}`;
|
|
7385
7385
|
|
|
7386
|
-
// packages/cli/src/
|
|
7387
|
-
import { lstatSync
|
|
7388
|
-
import {
|
|
7386
|
+
// packages/cli/src/core/privatePath.ts
|
|
7387
|
+
import { lstatSync } from "node:fs";
|
|
7388
|
+
import { open as open2 } from "node:fs/promises";
|
|
7389
|
+
|
|
7390
|
+
// packages/cli/src/core/windowsAcl.ts
|
|
7391
|
+
import { spawnSync } from "node:child_process";
|
|
7392
|
+
import { dirname, win32 } from "node:path";
|
|
7389
7393
|
|
|
7390
7394
|
// node_modules/zod/v4/classic/external.js
|
|
7391
7395
|
var external_exports = {};
|
|
@@ -27055,12 +27059,104 @@ function date4(params) {
|
|
|
27055
27059
|
return _coercedDate(ZodDate, params);
|
|
27056
27060
|
}
|
|
27057
27061
|
|
|
27062
|
+
// packages/cli/src/core/windowsAcl.ts
|
|
27063
|
+
var Sid = external_exports.string().regex(/^S-1-(?:\d+-)*\d+$/);
|
|
27064
|
+
var Inspection = external_exports.object({ owner: Sid, currentUser: Sid, reparse: external_exports.literal(false), rules: external_exports.array(external_exports.object({ sid: Sid, allow: external_exports.boolean(), rights: external_exports.number().int() })).min(1) });
|
|
27065
|
+
var WRITE_ACCESS = 852310 | 1342177280;
|
|
27066
|
+
function assertWindowsAcl(value, policy) {
|
|
27067
|
+
const parsed = Inspection.safeParse(value);
|
|
27068
|
+
if (!parsed.success) throw Error("WINDOWS_ACL_UNSAFE");
|
|
27069
|
+
const s = parsed.data, trusted = /* @__PURE__ */ new Set([s.currentUser, "S-1-5-18", "S-1-5-32-544"]);
|
|
27070
|
+
if (!trusted.has(s.owner) || s.rules.some((r) => r.allow && !trusted.has(r.sid) && (policy === "private" ? r.rights !== 0 : (r.rights & WRITE_ACCESS) !== 0))) throw Error("WINDOWS_ACL_UNSAFE");
|
|
27071
|
+
}
|
|
27072
|
+
var SCRIPT = String.raw`
|
|
27073
|
+
$ErrorActionPreference='Stop'
|
|
27074
|
+
[Console]::OutputEncoding=New-Object System.Text.UTF8Encoding($false)
|
|
27075
|
+
$p=[IO.Path]::GetFullPath($env:SBERPAY_ACL_PATH)
|
|
27076
|
+
$cursor=$p
|
|
27077
|
+
while($cursor){
|
|
27078
|
+
if(Test-Path -LiteralPath $cursor){
|
|
27079
|
+
$item=Get-Item -LiteralPath $cursor -Force
|
|
27080
|
+
if(($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0){throw 'REPARSE_POINT'}
|
|
27081
|
+
}
|
|
27082
|
+
$next=[IO.Path]::GetDirectoryName($cursor)
|
|
27083
|
+
if($next -eq $cursor){break};$cursor=$next
|
|
27084
|
+
}
|
|
27085
|
+
$sid=[Security.Principal.WindowsIdentity]::GetCurrent().User
|
|
27086
|
+
if($env:SBERPAY_ACL_ACTION -eq 'create' -and !(Test-Path -LiteralPath $p)){
|
|
27087
|
+
$acl=New-Object Security.AccessControl.DirectorySecurity
|
|
27088
|
+
$acl.SetOwner($sid);$acl.SetAccessRuleProtection($true,$false)
|
|
27089
|
+
foreach($id in @($sid.Value,'S-1-5-18','S-1-5-32-544')){
|
|
27090
|
+
$principal=New-Object Security.Principal.SecurityIdentifier($id)
|
|
27091
|
+
$rule=New-Object Security.AccessControl.FileSystemAccessRule($principal,'FullControl','ContainerInherit,ObjectInherit','None','Allow')
|
|
27092
|
+
$acl.AddAccessRule($rule)
|
|
27093
|
+
}
|
|
27094
|
+
[IO.Directory]::CreateDirectory($p,$acl)|Out-Null
|
|
27095
|
+
}
|
|
27096
|
+
$acl=Get-Acl -LiteralPath $p
|
|
27097
|
+
$rules=@($acl.GetAccessRules($true,$true,[Security.Principal.SecurityIdentifier])|ForEach-Object{
|
|
27098
|
+
@{sid=$_.IdentityReference.Value;allow=($_.AccessControlType -eq 'Allow');rights=[int]$_.FileSystemRights}
|
|
27099
|
+
})
|
|
27100
|
+
@{owner=$acl.GetOwner([Security.Principal.SecurityIdentifier]).Value;currentUser=$sid.Value;reparse=$false;rules=$rules}|ConvertTo-Json -Compress -Depth 5
|
|
27101
|
+
`;
|
|
27102
|
+
function windowsAclCommand(path2, action2, env = process.env) {
|
|
27103
|
+
const root = env.SystemRoot;
|
|
27104
|
+
if (!root || !win32.isAbsolute(root)) throw Error("WINDOWS_SYSTEM_ROOT_MISSING");
|
|
27105
|
+
return { file: win32.join(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe"), args: ["-NoLogo", "-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(SCRIPT, "utf16le").toString("base64")], env: { SystemRoot: root, SBERPAY_ACL_PATH: path2, SBERPAY_ACL_ACTION: action2 } };
|
|
27106
|
+
}
|
|
27107
|
+
function inspect(path2, policy, action2) {
|
|
27108
|
+
const c = windowsAclCommand(path2, action2);
|
|
27109
|
+
const r = spawnSync(c.file, c.args, { env: c.env, encoding: "utf8", windowsHide: true, timeout: 1e4, maxBuffer: 128 * 1024 });
|
|
27110
|
+
if (r.error || r.status !== 0) throw Error("WINDOWS_ACL_CHECK_FAILED");
|
|
27111
|
+
let value;
|
|
27112
|
+
try {
|
|
27113
|
+
value = JSON.parse(r.stdout.trim().replace(/^\uFEFF/, ""));
|
|
27114
|
+
} catch {
|
|
27115
|
+
throw Error("WINDOWS_ACL_CHECK_FAILED");
|
|
27116
|
+
}
|
|
27117
|
+
assertWindowsAcl(value, policy);
|
|
27118
|
+
}
|
|
27119
|
+
function assertWindowsPrivatePath(path2) {
|
|
27120
|
+
inspect(path2, "private", "inspect");
|
|
27121
|
+
}
|
|
27122
|
+
function ensureWindowsPrivateDirectory(path2) {
|
|
27123
|
+
inspect(path2, "private", "create");
|
|
27124
|
+
}
|
|
27125
|
+
function assertWindowsHelperPath(path2) {
|
|
27126
|
+
inspect(path2, "binary", "inspect");
|
|
27127
|
+
inspect(dirname(path2), "binary", "inspect");
|
|
27128
|
+
}
|
|
27129
|
+
|
|
27130
|
+
// packages/cli/src/core/privatePath.ts
|
|
27131
|
+
function assertPrivateFile(path2, info) {
|
|
27132
|
+
const named = lstatSync(path2);
|
|
27133
|
+
if (!info.isFile() || !named.isFile() || named.isSymbolicLink() || info.ino !== named.ino || info.dev !== named.dev) throw Error("UNSAFE_FILE");
|
|
27134
|
+
if (process.platform === "win32") assertWindowsPrivatePath(path2);
|
|
27135
|
+
else if (process.getuid && info.uid !== process.getuid() || info.mode & 63) throw Error("UNSAFE_FILE");
|
|
27136
|
+
}
|
|
27137
|
+
async function syncDirectory(path2) {
|
|
27138
|
+
if (process.platform === "win32") return;
|
|
27139
|
+
const f = await open2(path2, "r");
|
|
27140
|
+
try {
|
|
27141
|
+
await f.sync();
|
|
27142
|
+
} finally {
|
|
27143
|
+
await f.close();
|
|
27144
|
+
}
|
|
27145
|
+
}
|
|
27146
|
+
|
|
27147
|
+
// packages/cli/src/paymentMode/state.ts
|
|
27148
|
+
import { lstatSync as lstatSync2, readFileSync, openSync as openSync2, closeSync as closeSync2, fstatSync, constants } from "node:fs";
|
|
27149
|
+
import { join } from "node:path";
|
|
27150
|
+
|
|
27058
27151
|
// packages/cli/src/core/atomicFile.ts
|
|
27059
|
-
import { mkdirSync, openSync, writeFileSync, fsyncSync, closeSync, renameSync, rmSync } from "node:fs";
|
|
27060
|
-
import { dirname } from "node:path";
|
|
27152
|
+
import { mkdirSync, existsSync, openSync, writeFileSync, fsyncSync, closeSync, renameSync, rmSync } from "node:fs";
|
|
27153
|
+
import { dirname as dirname2 } from "node:path";
|
|
27061
27154
|
import { randomUUID } from "node:crypto";
|
|
27062
27155
|
function atomicJson(path2, value) {
|
|
27063
|
-
|
|
27156
|
+
if (process.platform === "win32") {
|
|
27157
|
+
ensureWindowsPrivateDirectory(dirname2(path2));
|
|
27158
|
+
if (existsSync(path2)) assertWindowsPrivatePath(path2);
|
|
27159
|
+
} else mkdirSync(dirname2(path2), { recursive: true, mode: 448 });
|
|
27064
27160
|
const temp = `${path2}.${randomUUID()}.tmp`;
|
|
27065
27161
|
try {
|
|
27066
27162
|
const fd2 = openSync(temp, "wx", 384);
|
|
@@ -27072,7 +27168,7 @@ function atomicJson(path2, value) {
|
|
|
27072
27168
|
}
|
|
27073
27169
|
renameSync(temp, path2);
|
|
27074
27170
|
if (process.platform !== "win32") {
|
|
27075
|
-
const dir2 = openSync(
|
|
27171
|
+
const dir2 = openSync(dirname2(path2), "r");
|
|
27076
27172
|
try {
|
|
27077
27173
|
fsyncSync(dir2);
|
|
27078
27174
|
} finally {
|
|
@@ -27182,8 +27278,9 @@ function invalid() {
|
|
|
27182
27278
|
throw new CliError(EXIT.CONFIG_OR_NETWORK, "PAYMENT_MODE_INVALID", "PAYMENT_MODE_INVALID: \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u0440\u0435\u0436\u0438\u043C\u0430 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043B\u0438 \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0435\u043D\u0430; \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 payment-mode set.");
|
|
27183
27279
|
}
|
|
27184
27280
|
function checkDir(paths) {
|
|
27185
|
-
const s =
|
|
27186
|
-
if (!s.isDirectory() || s.isSymbolicLink() || (s.mode & 63) !== 0) invalid();
|
|
27281
|
+
const s = lstatSync2(paths.configDir);
|
|
27282
|
+
if (!s.isDirectory() || s.isSymbolicLink() || process.platform !== "win32" && (s.mode & 63) !== 0) invalid();
|
|
27283
|
+
if (process.platform === "win32") assertWindowsPrivatePath(paths.configDir);
|
|
27187
27284
|
}
|
|
27188
27285
|
function readPaymentMode(paths) {
|
|
27189
27286
|
try {
|
|
@@ -27191,7 +27288,8 @@ function readPaymentMode(paths) {
|
|
|
27191
27288
|
const fd2 = openSync2(modeFile(paths), constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
27192
27289
|
try {
|
|
27193
27290
|
const s = fstatSync(fd2);
|
|
27194
|
-
|
|
27291
|
+
assertPrivateFile(modeFile(paths), s);
|
|
27292
|
+
if (s.size > 4096) invalid();
|
|
27195
27293
|
return PaymentModeStateSchema.parse(JSON.parse(readFileSync(fd2, "utf8")));
|
|
27196
27294
|
} finally {
|
|
27197
27295
|
closeSync2(fd2);
|
|
@@ -27209,7 +27307,7 @@ async function writePaymentMode(paths, state) {
|
|
|
27209
27307
|
if (e.code !== "ENOENT") throw e;
|
|
27210
27308
|
}
|
|
27211
27309
|
try {
|
|
27212
|
-
const s =
|
|
27310
|
+
const s = lstatSync2(modeFile(paths));
|
|
27213
27311
|
if (!s.isFile() || s.isSymbolicLink()) invalid();
|
|
27214
27312
|
} catch (e) {
|
|
27215
27313
|
if (e.code !== "ENOENT") throw e;
|
|
@@ -27222,8 +27320,8 @@ async function writePaymentMode(paths, state) {
|
|
|
27222
27320
|
var modeLabel = { live: "\u0420\u0435\u0430\u043B\u044C\u043D\u044B\u0435 \u043F\u043B\u0430\u0442\u0435\u0436\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u044B", blocked: "\u041E\u043F\u043B\u0430\u0442\u0430 \u043E\u0442\u043A\u043B\u044E\u0447\u0435\u043D\u0430", "invalid-token": "\u041F\u0440\u043E\u0431\u0430 \u0441 \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0451\u043D\u043D\u044B\u043C \u0442\u043E\u043A\u0435\u043D\u043E\u043C. \u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u043F\u0438\u0441\u0430\u043D\u0438\u044F \u043D\u0435 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u043E" };
|
|
27223
27321
|
|
|
27224
27322
|
// packages/cli/src/core/fileLock.ts
|
|
27225
|
-
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, rmSync as rmSync2, renameSync as renameSync2, existsSync } from "node:fs";
|
|
27226
|
-
import { dirname as
|
|
27323
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, rmSync as rmSync2, renameSync as renameSync2, existsSync as existsSync2 } from "node:fs";
|
|
27324
|
+
import { dirname as dirname3, join as join2 } from "node:path";
|
|
27227
27325
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
27228
27326
|
function processAlive(pid) {
|
|
27229
27327
|
if (!Number.isSafeInteger(pid) || pid <= 0) return void 0;
|
|
@@ -27260,7 +27358,7 @@ function owner(path2) {
|
|
|
27260
27358
|
}
|
|
27261
27359
|
}
|
|
27262
27360
|
async function withFileLock(path2, fn, timeoutMs = 5e3) {
|
|
27263
|
-
mkdirSync2(
|
|
27361
|
+
mkdirSync2(dirname3(path2), { recursive: true, mode: 448 });
|
|
27264
27362
|
const nonce2 = randomUUID2(), deadline = Date.now() + timeoutMs;
|
|
27265
27363
|
for (; ; ) {
|
|
27266
27364
|
try {
|
|
@@ -27287,7 +27385,7 @@ async function withFileLock(path2, fn, timeoutMs = 5e3) {
|
|
|
27287
27385
|
} finally {
|
|
27288
27386
|
if (acquired) rmSync2(reaper, { recursive: true, force: true });
|
|
27289
27387
|
}
|
|
27290
|
-
if (!
|
|
27388
|
+
if (!existsSync2(path2)) continue;
|
|
27291
27389
|
}
|
|
27292
27390
|
if (Date.now() >= deadline)
|
|
27293
27391
|
throw new CliError(EXIT.CONFIG_OR_NETWORK, "BINDING_BUSY", "\u0414\u0440\u0443\u0433\u0430\u044F \u043A\u043E\u043C\u0430\u043D\u0434\u0430 \u0432\u043B\u0430\u0434\u0435\u0435\u0442 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435\u043C \u0438\u043B\u0438 \u0432\u043B\u0430\u0434\u0435\u043B\u0435\u0446 \u0431\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u043A\u0438 \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043D. \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u043E\u0437\u0436\u0435.");
|
|
@@ -27304,7 +27402,7 @@ async function withFileLock(path2, fn, timeoutMs = 5e3) {
|
|
|
27304
27402
|
// packages/cli/src/probe/journal.ts
|
|
27305
27403
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
27306
27404
|
import {
|
|
27307
|
-
existsSync as
|
|
27405
|
+
existsSync as existsSync3,
|
|
27308
27406
|
mkdirSync as mkdirSync4,
|
|
27309
27407
|
readFileSync as readFileSync4,
|
|
27310
27408
|
rmSync as rmSync3,
|
|
@@ -27312,7 +27410,7 @@ import {
|
|
|
27312
27410
|
openSync as openSync4,
|
|
27313
27411
|
fsyncSync as fsyncSync3,
|
|
27314
27412
|
closeSync as closeSync4,
|
|
27315
|
-
lstatSync as
|
|
27413
|
+
lstatSync as lstatSync4
|
|
27316
27414
|
} from "node:fs";
|
|
27317
27415
|
import { join as join4 } from "node:path";
|
|
27318
27416
|
|
|
@@ -27364,7 +27462,7 @@ import {
|
|
|
27364
27462
|
closeSync as closeSync3,
|
|
27365
27463
|
fsyncSync as fsyncSync2,
|
|
27366
27464
|
fstatSync as fstatSync2,
|
|
27367
|
-
lstatSync as
|
|
27465
|
+
lstatSync as lstatSync3,
|
|
27368
27466
|
mkdirSync as mkdirSync3,
|
|
27369
27467
|
openSync as openSync3,
|
|
27370
27468
|
readFileSync as readFileSync3,
|
|
@@ -27381,14 +27479,16 @@ function journalError() {
|
|
|
27381
27479
|
);
|
|
27382
27480
|
}
|
|
27383
27481
|
function privateDir(path2) {
|
|
27384
|
-
|
|
27385
|
-
|
|
27482
|
+
if (process.platform === "win32") ensureWindowsPrivateDirectory(path2);
|
|
27483
|
+
else mkdirSync3(path2, { recursive: true, mode: 448 });
|
|
27484
|
+
const s = lstatSync3(path2);
|
|
27386
27485
|
if (!s.isDirectory() || s.isSymbolicLink() || process.platform !== "win32" && ((s.mode & 63) !== 0 || s.uid !== process.getuid?.()))
|
|
27387
27486
|
journalError();
|
|
27388
27487
|
}
|
|
27389
27488
|
function registryDir(paths) {
|
|
27390
|
-
|
|
27391
|
-
|
|
27489
|
+
if (process.platform === "win32") ensureWindowsPrivateDirectory(paths.stateDir);
|
|
27490
|
+
else mkdirSync3(paths.stateDir, { recursive: true, mode: 448 });
|
|
27491
|
+
if (lstatSync3(paths.stateDir).isSymbolicLink()) journalError();
|
|
27392
27492
|
const dir2 = join3(paths.stateDir, "payment-probes");
|
|
27393
27493
|
privateDir(dir2);
|
|
27394
27494
|
return dir2;
|
|
@@ -27405,6 +27505,12 @@ function syncDir(dir2) {
|
|
|
27405
27505
|
function openPrivate(path2, flags) {
|
|
27406
27506
|
const fd2 = openSync3(path2, flags | (constants2.O_NOFOLLOW ?? 0), 384);
|
|
27407
27507
|
const s = fstatSync2(fd2);
|
|
27508
|
+
try {
|
|
27509
|
+
assertPrivateFile(path2, s);
|
|
27510
|
+
} catch {
|
|
27511
|
+
closeSync3(fd2);
|
|
27512
|
+
journalError();
|
|
27513
|
+
}
|
|
27408
27514
|
if (!s.isFile() || s.nlink !== 1 || s.size > MAX_FILE || process.platform !== "win32" && ((s.mode & 63) !== 0 || s.uid !== process.getuid?.())) {
|
|
27409
27515
|
closeSync3(fd2);
|
|
27410
27516
|
journalError();
|
|
@@ -27649,7 +27755,7 @@ function lockError(code) {
|
|
|
27649
27755
|
}
|
|
27650
27756
|
function ownerAlive(lock) {
|
|
27651
27757
|
try {
|
|
27652
|
-
if (
|
|
27758
|
+
if (lstatSync4(lock).isSymbolicLink()) journalError();
|
|
27653
27759
|
const raw = readFileSync4(join4(lock, "owner.json"), "utf8");
|
|
27654
27760
|
if (raw.length > 256) journalError();
|
|
27655
27761
|
const pid = JSON.parse(raw).pid;
|
|
@@ -27668,7 +27774,7 @@ function ownerAlive(lock) {
|
|
|
27668
27774
|
async function exclusive(paths, recover, fn, installing2 = false) {
|
|
27669
27775
|
const dir2 = registryDir(paths), lock = join4(dir2, ".lock");
|
|
27670
27776
|
let recovered = false;
|
|
27671
|
-
if (
|
|
27777
|
+
if (existsSync3(lock)) {
|
|
27672
27778
|
if (ownerAlive(lock)) lockError("PROBE_BUSY");
|
|
27673
27779
|
if (!recover) lockError("PROBE_STALE_LOCK");
|
|
27674
27780
|
try {
|
|
@@ -27704,7 +27810,7 @@ async function exclusive(paths, recover, fn, installing2 = false) {
|
|
|
27704
27810
|
}
|
|
27705
27811
|
syncDir(lock);
|
|
27706
27812
|
syncDir(dir2);
|
|
27707
|
-
if (!installing2 &&
|
|
27813
|
+
if (!installing2 && existsSync3(join4(paths.configDir, "../..", "install-pending.json")))
|
|
27708
27814
|
throw new CliError(EXIT.CONFIG_OR_NETWORK, "INSTALL_IN_PROGRESS", "\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430 \u043D\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430");
|
|
27709
27815
|
return await fn();
|
|
27710
27816
|
} finally {
|
|
@@ -28054,13 +28160,13 @@ function cliPaths(env = process.env) {
|
|
|
28054
28160
|
}
|
|
28055
28161
|
|
|
28056
28162
|
// packages/cli/src/report/storage.ts
|
|
28057
|
-
import { lstatSync as
|
|
28163
|
+
import { lstatSync as lstatSync5, mkdirSync as mkdirSync6, readdirSync as readdirSync2, unlinkSync } from "node:fs";
|
|
28058
28164
|
import { join as join7 } from "node:path";
|
|
28059
28165
|
|
|
28060
28166
|
// packages/cli/src/report/bindingFiles.ts
|
|
28061
|
-
import { open as
|
|
28167
|
+
import { open as open3, realpath, stat } from "node:fs/promises";
|
|
28062
28168
|
import { constants as constants3 } from "node:fs";
|
|
28063
|
-
import { dirname as
|
|
28169
|
+
import { dirname as dirname4, isAbsolute, relative, resolve } from "node:path";
|
|
28064
28170
|
var BindingError = class extends Error {
|
|
28065
28171
|
constructor(code, hint, reasonCode) {
|
|
28066
28172
|
super(code);
|
|
@@ -28090,7 +28196,7 @@ async function futurePath(root, path2) {
|
|
|
28090
28196
|
return target;
|
|
28091
28197
|
} catch (error62) {
|
|
28092
28198
|
if (error62.code !== "ENOENT") throw error62;
|
|
28093
|
-
const parent =
|
|
28199
|
+
const parent = dirname4(ancestor);
|
|
28094
28200
|
if (parent === ancestor) throw new BindingError("PATH_OUTSIDE_ROOT");
|
|
28095
28201
|
ancestor = parent;
|
|
28096
28202
|
}
|
|
@@ -28100,9 +28206,10 @@ async function readPrefix(root, path2, maxBytes = 256 * 1024) {
|
|
|
28100
28206
|
const canonicalRoot = await realpath(root);
|
|
28101
28207
|
const canonical = await realpath(path2);
|
|
28102
28208
|
if (!contained(canonicalRoot, canonical)) throw new BindingError("PATH_OUTSIDE_ROOT");
|
|
28209
|
+
if (process.platform === "win32") assertWindowsHelperPath(canonical);
|
|
28103
28210
|
const before = await stat(canonical);
|
|
28104
28211
|
if (!before.isFile() || process.getuid && before.uid !== process.getuid()) throw new BindingError("UNSAFE_SOURCE");
|
|
28105
|
-
const file2 = await
|
|
28212
|
+
const file2 = await open3(canonical, constants3.O_RDONLY | (constants3.O_NOFOLLOW ?? 0) | (constants3.O_NONBLOCK ?? 0));
|
|
28106
28213
|
try {
|
|
28107
28214
|
const now = await file2.stat();
|
|
28108
28215
|
if (!now.isFile() || now.ino !== before.ino || now.dev !== before.dev) throw new BindingError("SOURCE_CHANGED");
|
|
@@ -28121,9 +28228,10 @@ async function readPrefix(root, path2, maxBytes = 256 * 1024) {
|
|
|
28121
28228
|
|
|
28122
28229
|
// packages/cli/src/report/storage.ts
|
|
28123
28230
|
function privateDir2(path2) {
|
|
28124
|
-
|
|
28125
|
-
|
|
28126
|
-
|
|
28231
|
+
if (process.platform === "win32") ensureWindowsPrivateDirectory(path2);
|
|
28232
|
+
else mkdirSync6(path2, { recursive: true, mode: 448 });
|
|
28233
|
+
const info = lstatSync5(path2);
|
|
28234
|
+
if (!info.isDirectory() || info.isSymbolicLink() || process.getuid && info.uid !== process.getuid() || process.platform !== "win32" && info.mode & 63) throw new BindingError("UNSAFE_REPORT_DIRECTORY");
|
|
28127
28235
|
return path2;
|
|
28128
28236
|
}
|
|
28129
28237
|
function retain(dir2, pattern, maxBytes) {
|
|
@@ -28131,7 +28239,7 @@ function retain(dir2, pattern, maxBytes) {
|
|
|
28131
28239
|
if (entries.length > 1e4) throw new BindingError("REPORT_STORAGE_ENTRY_LIMIT");
|
|
28132
28240
|
const files = entries.filter((name) => pattern.test(name)).flatMap((name) => {
|
|
28133
28241
|
const path2 = join7(dir2, name);
|
|
28134
|
-
const info =
|
|
28242
|
+
const info = lstatSync5(path2);
|
|
28135
28243
|
return info.isFile() && !info.isSymbolicLink() ? [{ path: path2, size: info.size, mtime: info.mtimeMs }] : [];
|
|
28136
28244
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
28137
28245
|
let total = 0;
|
|
@@ -28143,7 +28251,7 @@ function retain(dir2, pattern, maxBytes) {
|
|
|
28143
28251
|
|
|
28144
28252
|
// packages/cli/src/report/transport.ts
|
|
28145
28253
|
import { constants as constants4 } from "node:fs";
|
|
28146
|
-
import { open as
|
|
28254
|
+
import { open as open4, lstat, rename, rm, mkdir } from "node:fs/promises";
|
|
28147
28255
|
import { join as join8 } from "node:path";
|
|
28148
28256
|
import { request as httpsRequest } from "node:https";
|
|
28149
28257
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
@@ -28223,10 +28331,11 @@ function validatePackage(bytes, caseId) {
|
|
|
28223
28331
|
|
|
28224
28332
|
// packages/cli/src/report/transport.ts
|
|
28225
28333
|
async function privateRead(path2, limit) {
|
|
28226
|
-
const file2 = await
|
|
28334
|
+
const file2 = await open4(path2, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
|
|
28227
28335
|
try {
|
|
28228
28336
|
const info = await file2.stat();
|
|
28229
|
-
|
|
28337
|
+
assertPrivateFile(path2, info);
|
|
28338
|
+
if (info.size > limit) throw Error("UNSAFE_FILE");
|
|
28230
28339
|
const buffer = Buffer.alloc(info.size);
|
|
28231
28340
|
let at = 0;
|
|
28232
28341
|
while (at < buffer.length) {
|
|
@@ -28275,7 +28384,7 @@ async function save(dir2, state) {
|
|
|
28275
28384
|
const temp = join8(dir2, `.${randomUUID4()}.tmp`);
|
|
28276
28385
|
const path2 = join8(dir2, `${state.caseId}.json`);
|
|
28277
28386
|
try {
|
|
28278
|
-
const file2 = await
|
|
28387
|
+
const file2 = await open4(temp, "wx", 384);
|
|
28279
28388
|
try {
|
|
28280
28389
|
await file2.writeFile(JSON.stringify({ ...state, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }));
|
|
28281
28390
|
await file2.sync();
|
|
@@ -28392,7 +28501,7 @@ import { homedir as homedir3 } from "node:os";
|
|
|
28392
28501
|
import { join as join9 } from "node:path";
|
|
28393
28502
|
|
|
28394
28503
|
// packages/cli/src/report/adapters/transcript.ts
|
|
28395
|
-
import { open as
|
|
28504
|
+
import { open as open5, realpath as realpath2, stat as stat2 } from "node:fs/promises";
|
|
28396
28505
|
import { constants as constants5 } from "node:fs";
|
|
28397
28506
|
import { relative as relative2, isAbsolute as isAbsolute2 } from "node:path";
|
|
28398
28507
|
import { createHash as createHash3 } from "node:crypto";
|
|
@@ -28495,13 +28604,14 @@ async function collectTranscript(agent, parser3, binding, options = {}) {
|
|
|
28495
28604
|
warn(result, "PATH_OUTSIDE_ROOT");
|
|
28496
28605
|
return result;
|
|
28497
28606
|
}
|
|
28607
|
+
if (process.platform === "win32") assertWindowsHelperPath(path2);
|
|
28498
28608
|
const before = await stat2(path2);
|
|
28499
28609
|
if (!before.isFile()) {
|
|
28500
28610
|
result.coverage = "failed";
|
|
28501
28611
|
warn(result, "UNSAFE_SOURCE");
|
|
28502
28612
|
return result;
|
|
28503
28613
|
}
|
|
28504
|
-
handle = await
|
|
28614
|
+
handle = await open5(path2, constants5.O_RDONLY | (constants5.O_NOFOLLOW ?? 0) | (constants5.O_NONBLOCK ?? 0));
|
|
28505
28615
|
const snapshot = await handle.stat();
|
|
28506
28616
|
if (!snapshot.isFile() || snapshot.ino !== before.ino || snapshot.dev !== before.dev || process.getuid && snapshot.uid !== process.getuid()) {
|
|
28507
28617
|
result.coverage = "failed";
|
|
@@ -28783,6 +28893,7 @@ async function codexBinding(env) {
|
|
|
28783
28893
|
const dbPath = await realpath3(join9(home, name));
|
|
28784
28894
|
const info = await stat3(dbPath);
|
|
28785
28895
|
if (!contained(home, dbPath) || !info.isFile() || process.getuid && info.uid !== process.getuid()) throw new BindingError("UNSAFE_INDEX");
|
|
28896
|
+
if (process.platform === "win32") assertWindowsHelperPath(dbPath);
|
|
28786
28897
|
const db = new DatabaseSync(dbPath, { readOnly: true });
|
|
28787
28898
|
try {
|
|
28788
28899
|
db.exec("PRAGMA query_only=ON; PRAGMA busy_timeout=500");
|
|
@@ -29587,7 +29698,7 @@ function zipSync(data, opts) {
|
|
|
29587
29698
|
}
|
|
29588
29699
|
|
|
29589
29700
|
// packages/cli/src/core/version.ts
|
|
29590
|
-
var CLI_VERSION = "0.4.0-dev.
|
|
29701
|
+
var CLI_VERSION = "0.4.0-dev.7";
|
|
29591
29702
|
|
|
29592
29703
|
// packages/cli/src/report/journal.ts
|
|
29593
29704
|
import { closeSync as closeSync5, constants as constants6, openSync as openSync5, writeSync as writeSync2 } from "node:fs";
|
|
@@ -30606,7 +30717,7 @@ function registerPaymentModeCommands(program3) {
|
|
|
30606
30717
|
|
|
30607
30718
|
// packages/cli/src/report/enrollment.ts
|
|
30608
30719
|
import { generateKeyPairSync, createHash as createHash8, createPrivateKey, createPublicKey, randomUUID as randomUUID8, sign } from "node:crypto";
|
|
30609
|
-
import { open as
|
|
30720
|
+
import { open as open6, rename as rename4, rm as rm4 } from "node:fs/promises";
|
|
30610
30721
|
import { join as join14 } from "node:path";
|
|
30611
30722
|
import { request as httpsRequest2 } from "node:https";
|
|
30612
30723
|
var DIAGNOSTIC_ENDPOINT = "https://aiplatilka.ru/case-reports";
|
|
@@ -30640,14 +30751,6 @@ var enrollmentPost = (path2, body) => new Promise((resolve6, reject) => {
|
|
|
30640
30751
|
request.on("error", reject);
|
|
30641
30752
|
request.end(bytes);
|
|
30642
30753
|
});
|
|
30643
|
-
async function syncDir2(dir2) {
|
|
30644
|
-
const f = await open5(dir2, "r");
|
|
30645
|
-
try {
|
|
30646
|
-
await f.sync();
|
|
30647
|
-
} finally {
|
|
30648
|
-
await f.close();
|
|
30649
|
-
}
|
|
30650
|
-
}
|
|
30651
30754
|
async function enrollInvitation(path2, env = process.env, request = enrollmentPost) {
|
|
30652
30755
|
try {
|
|
30653
30756
|
const invite = Invitation.parse(JSON.parse((await privateRead(path2, 8192)).toString("utf8")));
|
|
@@ -30656,20 +30759,20 @@ async function enrollInvitation(path2, env = process.env, request = enrollmentPo
|
|
|
30656
30759
|
const statePath = join14(dir2, "report-installation.json");
|
|
30657
30760
|
try {
|
|
30658
30761
|
const pair = generateKeyPairSync("ed25519");
|
|
30659
|
-
const file2 = await
|
|
30762
|
+
const file2 = await open6(statePath, "wx", 384);
|
|
30660
30763
|
try {
|
|
30661
30764
|
await file2.writeFile(JSON.stringify({ invitationHash: hash3, installationId: randomUUID8(), privateKey: pair.privateKey.export({ format: "pem", type: "pkcs8" }), publicKey: pair.publicKey.export({ format: "pem", type: "spki" }) }));
|
|
30662
30765
|
await file2.sync();
|
|
30663
30766
|
} finally {
|
|
30664
30767
|
await file2.close();
|
|
30665
30768
|
}
|
|
30666
|
-
await
|
|
30769
|
+
await syncDirectory(dir2);
|
|
30667
30770
|
} catch (error62) {
|
|
30668
30771
|
if (error62.code !== "EEXIST") throw error62;
|
|
30669
30772
|
}
|
|
30670
30773
|
const state = State.parse(JSON.parse((await privateRead(statePath, 8192)).toString("utf8")));
|
|
30671
30774
|
if (state.invitationHash !== hash3 || createPublicKey(state.privateKey).export({ format: "pem", type: "spki" }).toString() !== state.publicKey) throw Error("INSTALLATION_CONFLICT");
|
|
30672
|
-
await
|
|
30775
|
+
await syncDirectory(dir2);
|
|
30673
30776
|
const body = { inviteToken: invite.token, installationId: state.installationId, publicKey: state.publicKey };
|
|
30674
30777
|
const challenge = external_exports.object({ challenge: external_exports.string().max(2048) }).strict().parse(await request("/v1/enroll/challenge", body));
|
|
30675
30778
|
const signature = sign(null, Buffer.from("sberpay-enroll-v1\n" + challenge.challenge), createPrivateKey(state.privateKey)).toString("base64url");
|
|
@@ -30677,7 +30780,7 @@ async function enrollInvitation(path2, env = process.env, request = enrollmentPo
|
|
|
30677
30780
|
if (response.installationId !== state.installationId) throw Error("INSTALLATION_MISMATCH");
|
|
30678
30781
|
const temp = join14(dir2, `.upload-${randomUUID8()}.tmp`);
|
|
30679
30782
|
try {
|
|
30680
|
-
const file2 = await
|
|
30783
|
+
const file2 = await open6(temp, "wx", 384);
|
|
30681
30784
|
try {
|
|
30682
30785
|
await file2.writeFile(JSON.stringify({ endpoint: DIAGNOSTIC_ENDPOINT, token: response.token }));
|
|
30683
30786
|
await file2.sync();
|
|
@@ -30685,7 +30788,7 @@ async function enrollInvitation(path2, env = process.env, request = enrollmentPo
|
|
|
30685
30788
|
await file2.close();
|
|
30686
30789
|
}
|
|
30687
30790
|
await rename4(temp, join14(dir2, "report-upload.json"));
|
|
30688
|
-
await
|
|
30791
|
+
await syncDirectory(dir2);
|
|
30689
30792
|
} finally {
|
|
30690
30793
|
await rm4(temp, { force: true });
|
|
30691
30794
|
}
|
|
@@ -34065,10 +34168,11 @@ var program = new Command();
|
|
|
34065
34168
|
|
|
34066
34169
|
// packages/cli/src/report/command.ts
|
|
34067
34170
|
import { homedir as homedir5 } from "node:os";
|
|
34068
|
-
import { join as join16, dirname as
|
|
34171
|
+
import { join as join16, dirname as dirname6, resolve as resolve2 } from "node:path";
|
|
34069
34172
|
|
|
34070
34173
|
// packages/cli/src/report/claudeHook.ts
|
|
34071
|
-
import {
|
|
34174
|
+
import { dirname as dirname5 } from "node:path";
|
|
34175
|
+
import { open as open7, chmod, lstat as lstat3, mkdir as mkdir2, readFile as readFile2, realpath as realpath4, rename as rename5, writeFile as writeFile4 } from "node:fs/promises";
|
|
34072
34176
|
import { constants as constants7 } from "node:fs";
|
|
34073
34177
|
import { homedir as homedir4 } from "node:os";
|
|
34074
34178
|
import { join as join15 } from "node:path";
|
|
@@ -34085,7 +34189,16 @@ async function captureClaudeBinding(input2, env = process.env) {
|
|
|
34085
34189
|
if (/[\r\n\0]/.test(path2 + config2)) throw new BindingError("INVALID_HOOK_PATH");
|
|
34086
34190
|
const lines = [["SBERPAY_CLAUDE_SESSION_ID", data.session_id], ["SBERPAY_CLAUDE_TRANSCRIPT", path2], ["SBERPAY_CLAUDE_CONFIG_DIR", config2]].map(([key, value]) => `export ${key}=${shellQuote(value)}
|
|
34087
34191
|
`).join("");
|
|
34088
|
-
|
|
34192
|
+
if (process.platform === "win32") {
|
|
34193
|
+
assertWindowsPrivatePath(dirname5(env.CLAUDE_ENV_FILE));
|
|
34194
|
+
try {
|
|
34195
|
+
await lstat3(env.CLAUDE_ENV_FILE);
|
|
34196
|
+
assertWindowsPrivatePath(env.CLAUDE_ENV_FILE);
|
|
34197
|
+
} catch (e) {
|
|
34198
|
+
if (e.code !== "ENOENT") throw e;
|
|
34199
|
+
}
|
|
34200
|
+
}
|
|
34201
|
+
const file2 = await open7(env.CLAUDE_ENV_FILE, constants7.O_WRONLY | constants7.O_APPEND | constants7.O_CREAT | (constants7.O_NOFOLLOW ?? 0) | (constants7.O_NONBLOCK ?? 0), 384);
|
|
34089
34202
|
try {
|
|
34090
34203
|
const info = await file2.stat();
|
|
34091
34204
|
if (!info.isFile() || process.getuid && info.uid !== process.getuid()) throw new BindingError("UNSAFE_ENV_FILE");
|
|
@@ -34095,12 +34208,14 @@ async function captureClaudeBinding(input2, env = process.env) {
|
|
|
34095
34208
|
}
|
|
34096
34209
|
}
|
|
34097
34210
|
async function installClaudeHook(configDir, command) {
|
|
34098
|
-
|
|
34211
|
+
if (process.platform === "win32") ensureWindowsPrivateDirectory(configDir);
|
|
34212
|
+
else await mkdir2(configDir, { recursive: true, mode: 448 });
|
|
34099
34213
|
const path2 = join15(configDir, "settings.json");
|
|
34100
34214
|
let original;
|
|
34101
34215
|
try {
|
|
34102
34216
|
const info = await lstat3(path2);
|
|
34103
34217
|
if (!info.isFile() || info.isSymbolicLink()) throw new BindingError("UNSAFE_SETTINGS");
|
|
34218
|
+
if (process.platform === "win32") assertWindowsPrivatePath(path2);
|
|
34104
34219
|
original = await readFile2(path2, "utf8");
|
|
34105
34220
|
} catch (error62) {
|
|
34106
34221
|
if (error62.code !== "ENOENT") throw error62;
|
|
@@ -34132,7 +34247,7 @@ async function installClaudeHook(configDir, command) {
|
|
|
34132
34247
|
// packages/cli/src/report/command.ts
|
|
34133
34248
|
function claudeHookCommand() {
|
|
34134
34249
|
const args = BUILD.kind === "release" ? [process.execPath, join16(BUILD.root, "dist", "cli.mjs")] : [process.execPath, "--import", import.meta.resolve("tsx"), join16(BUILD.root, "packages", "cli", "src", "main.ts")];
|
|
34135
|
-
return [...args, "report", "claude-hook"].map(shellQuote).join(" ");
|
|
34250
|
+
return [...args, "report", "claude-hook"].map((s) => shellQuote(process.platform === "win32" ? s.replaceAll("\\", "/") : s)).join(" ");
|
|
34136
34251
|
}
|
|
34137
34252
|
async function hookInput() {
|
|
34138
34253
|
const chunks = [];
|
|
@@ -34196,7 +34311,7 @@ function registerReportCommands(program3) {
|
|
|
34196
34311
|
for (const name of ["collect", "submit"]) report2.command(name).description(name === "collect" ? "\u0421\u043E\u0431\u0440\u0430\u0442\u044C \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u044B\u0439 ZIP \u0442\u0435\u043A\u0443\u0449\u0435\u0433\u043E \u0447\u0430\u0442\u0430" : "\u0421\u043E\u0431\u0440\u0430\u0442\u044C \u043A\u0435\u0439\u0441 \u0438 \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0432 \u043D\u0430\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0439 HTTPS-\u043F\u0440\u0438\u0451\u043C\u043D\u0438\u043A").requiredOption("--input <path>", "JSON: title, scope=current_session, \u043D\u0435\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0435 request/expected/observed/agentSummary/hypotheses").addOption(new Option("--agent <agent>", "\u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A \u0442\u0435\u043A\u0443\u0449\u0435\u0439 \u0441\u0435\u0441\u0441\u0438\u0438").choices(["auto", "codex", "claude"]).default("auto")).action(async (opts) => {
|
|
34197
34312
|
try {
|
|
34198
34313
|
const path2 = resolve2(opts.input);
|
|
34199
|
-
const text2 = await readPrefix(
|
|
34314
|
+
const text2 = await readPrefix(dirname6(path2), path2, 65537);
|
|
34200
34315
|
if (Buffer.byteLength(text2) > 65536) throw new BindingError("CASE_INPUT_LIMIT");
|
|
34201
34316
|
let input2;
|
|
34202
34317
|
try {
|
|
@@ -34429,7 +34544,7 @@ function softwareDeviceKeys(storage, where = "os") {
|
|
|
34429
34544
|
}
|
|
34430
34545
|
|
|
34431
34546
|
// packages/device/src/helper.ts
|
|
34432
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
34547
|
+
import { spawn, spawnSync as spawnSync2 } from "node:child_process";
|
|
34433
34548
|
var HELPER_PROTOCOL = 1;
|
|
34434
34549
|
var TIMEOUT_MS = 15e3;
|
|
34435
34550
|
var MAX_OUTPUT_BYTES = 64 * 1024;
|
|
@@ -34497,7 +34612,7 @@ async function callHelper(path2, request, schema) {
|
|
|
34497
34612
|
return parseReply(request.op, code, stdout, schema);
|
|
34498
34613
|
}
|
|
34499
34614
|
function callHelperSync(path2, request, schema) {
|
|
34500
|
-
const result =
|
|
34615
|
+
const result = spawnSync2(path2, [], {
|
|
34501
34616
|
input: encode3(request),
|
|
34502
34617
|
env: helperEnv(),
|
|
34503
34618
|
stdio: ["pipe", "pipe", "ignore"],
|
|
@@ -34527,8 +34642,8 @@ function helperSecrets(helper) {
|
|
|
34527
34642
|
|
|
34528
34643
|
// packages/device/src/hardware.ts
|
|
34529
34644
|
import { createPublicKey as createPublicKey3, verify } from "node:crypto";
|
|
34530
|
-
import { chmodSync, closeSync as closeSync6, existsSync as
|
|
34531
|
-
import { dirname as
|
|
34645
|
+
import { chmodSync, closeSync as closeSync6, existsSync as existsSync4, fsyncSync as fsyncSync4, linkSync, mkdirSync as mkdirSync7, openSync as openSync6, readFileSync as readFileSync6, rmSync as rmSync4, writeSync as writeSync3 } from "node:fs";
|
|
34646
|
+
import { dirname as dirname7 } from "node:path";
|
|
34532
34647
|
var B64URL2 = external_exports.string().max(4096).regex(/^[A-Za-z0-9_-]+$/);
|
|
34533
34648
|
var Point = external_exports.object({ x: B64URL2, y: B64URL2 });
|
|
34534
34649
|
var Blobs = external_exports.object({ signKey: B64URL2, encKey: B64URL2 });
|
|
@@ -34544,7 +34659,7 @@ function toPublicKeys(pub) {
|
|
|
34544
34659
|
return { deviceId: jwkThumbprint(publicKey), publicKey, encKey: jwk(pub.encPublicKey, "enc") };
|
|
34545
34660
|
}
|
|
34546
34661
|
function readBlobs(file2, kind2) {
|
|
34547
|
-
if (!
|
|
34662
|
+
if (!existsSync4(file2)) return void 0;
|
|
34548
34663
|
const parsed = KeyFile.safeParse((() => {
|
|
34549
34664
|
try {
|
|
34550
34665
|
return JSON.parse(readFileSync6(file2, "utf8"));
|
|
@@ -34556,7 +34671,7 @@ function readBlobs(file2, kind2) {
|
|
|
34556
34671
|
return { signKey: parsed.data.signKey, encKey: parsed.data.encKey };
|
|
34557
34672
|
}
|
|
34558
34673
|
function saveNewBlobs(file2, kind2, blobs) {
|
|
34559
|
-
mkdirSync7(
|
|
34674
|
+
mkdirSync7(dirname7(file2), { recursive: true, mode: 448 });
|
|
34560
34675
|
const tmp = `${file2}.${process.pid}.${Date.now()}.tmp`;
|
|
34561
34676
|
const fd2 = openSync6(tmp, "wx", 384);
|
|
34562
34677
|
try {
|
|
@@ -34589,7 +34704,7 @@ function checkSignature(pub, data, signature) {
|
|
|
34589
34704
|
return signature;
|
|
34590
34705
|
}
|
|
34591
34706
|
async function hardwareAvailable(helper) {
|
|
34592
|
-
if (!
|
|
34707
|
+
if (!existsSync4(helper)) return false;
|
|
34593
34708
|
try {
|
|
34594
34709
|
return (await callHelper(helper, { op: "status" }, external_exports.object({ available: external_exports.boolean() }))).available;
|
|
34595
34710
|
} catch {
|
|
@@ -34619,7 +34734,7 @@ function hardwareDeviceKeys({ kind: kind2, helper, file: file2 }) {
|
|
|
34619
34734
|
return {
|
|
34620
34735
|
kind: kind2,
|
|
34621
34736
|
storage: "hardware",
|
|
34622
|
-
exists: () => Boolean(blobs) ||
|
|
34737
|
+
exists: () => Boolean(blobs) || existsSync4(file2),
|
|
34623
34738
|
ensure: publicKeys,
|
|
34624
34739
|
async sign(data) {
|
|
34625
34740
|
const signKey = required2().signKey;
|
|
@@ -34653,7 +34768,7 @@ function hardwareDeviceKeys({ kind: kind2, helper, file: file2 }) {
|
|
|
34653
34768
|
}
|
|
34654
34769
|
|
|
34655
34770
|
// packages/cli/src/core/context.ts
|
|
34656
|
-
import { appendFileSync, mkdirSync as mkdirSync9 } from "node:fs";
|
|
34771
|
+
import { appendFileSync, mkdirSync as mkdirSync9, existsSync as existsSync8 } from "node:fs";
|
|
34657
34772
|
import { join as join20 } from "node:path";
|
|
34658
34773
|
|
|
34659
34774
|
// packages/netlog/src/masking.ts
|
|
@@ -34829,7 +34944,7 @@ async function loggedFetch(logger, meta3, url2, init = {}) {
|
|
|
34829
34944
|
}
|
|
34830
34945
|
|
|
34831
34946
|
// packages/cli/src/core/config.ts
|
|
34832
|
-
import { existsSync as
|
|
34947
|
+
import { existsSync as existsSync5, readFileSync as readFileSync8 } from "node:fs";
|
|
34833
34948
|
import { join as join17 } from "node:path";
|
|
34834
34949
|
var STAND_NAMES = ["local", "ift", "prod"];
|
|
34835
34950
|
var KEY_STORAGE_PREFERENCES = [
|
|
@@ -34853,7 +34968,7 @@ var DEFAULT_STANDS = {
|
|
|
34853
34968
|
ift: { allowSoftwareKeys: true },
|
|
34854
34969
|
// Шлюз ЭК ПРОМ (ЭлКом вышел на ПРОМ 07.10.2026). Реестр ФП временно на aiplatilka.ru. Кабинет под tsx — в config.json:
|
|
34855
34970
|
// cabinetMockUrl для токена, выпущенного ЭлКом вручную, или cabinetOrigins и cabinetBaseUrl.
|
|
34856
|
-
prod: { gatewayUrl: PROD_GATEWAY, merchantsUrl: PROD_MERCHANTS, addressesUrl: "https://aiplatilka.ru", addressesMode: "pilot-json", allowSoftwareKeys:
|
|
34971
|
+
prod: { gatewayUrl: PROD_GATEWAY, merchantsUrl: PROD_MERCHANTS, addressesUrl: "https://aiplatilka.ru", addressesMode: "pilot-json", allowSoftwareKeys: true }
|
|
34857
34972
|
};
|
|
34858
34973
|
var RELEASE_PROD = {
|
|
34859
34974
|
gatewayUrl: PROD_GATEWAY,
|
|
@@ -34863,7 +34978,7 @@ var RELEASE_PROD = {
|
|
|
34863
34978
|
cabinetOrigins: [PROD_CABINET],
|
|
34864
34979
|
cabinetBaseUrl: PROD_CABINET,
|
|
34865
34980
|
staticUrl: PROD_CABINET,
|
|
34866
|
-
allowSoftwareKeys:
|
|
34981
|
+
allowSoftwareKeys: true
|
|
34867
34982
|
};
|
|
34868
34983
|
var RELEASE_LOCKED = {
|
|
34869
34984
|
local: ["cabinetMockUrl"],
|
|
@@ -34890,8 +35005,9 @@ function isStand(value) {
|
|
|
34890
35005
|
}
|
|
34891
35006
|
function loadConfig(paths, build = BUILD) {
|
|
34892
35007
|
const file2 = join17(paths.configDir, "config.json");
|
|
34893
|
-
if (!
|
|
35008
|
+
if (!existsSync5(file2)) return defaultConfig(build);
|
|
34894
35009
|
try {
|
|
35010
|
+
if (process.platform === "win32") assertWindowsPrivatePath(file2);
|
|
34895
35011
|
return { ...defaultConfig(build), ...JSON.parse(readFileSync8(file2, "utf8")) };
|
|
34896
35012
|
} catch (error62) {
|
|
34897
35013
|
throw new CliError(
|
|
@@ -35004,7 +35120,7 @@ function resolveStand(config2, name, build = BUILD) {
|
|
|
35004
35120
|
if (merged.cabinetBaseUrl && !realOrigins.includes(new URL(merged.cabinetBaseUrl).origin)) {
|
|
35005
35121
|
invalidField(name, "cabinetBaseUrl", "\u0430\u0434\u0440\u0435\u0441 \u043A\u0430\u0431\u0438\u043D\u0435\u0442\u0430 \u0441 origin \u0438\u0437 cabinetOrigins");
|
|
35006
35122
|
}
|
|
35007
|
-
const allowSoftwareKeys =
|
|
35123
|
+
const allowSoftwareKeys = merged.allowSoftwareKeys !== false;
|
|
35008
35124
|
return { ...merged, cabinetOrigins: mock ? [...realOrigins, mock] : realOrigins, allowSoftwareKeys };
|
|
35009
35125
|
}
|
|
35010
35126
|
async function updateConfig(paths, transform3) {
|
|
@@ -35018,7 +35134,7 @@ async function updateConfig(paths, transform3) {
|
|
|
35018
35134
|
// packages/cli/src/core/secrets.ts
|
|
35019
35135
|
import {
|
|
35020
35136
|
chmodSync as chmodSync2,
|
|
35021
|
-
existsSync as
|
|
35137
|
+
existsSync as existsSync7,
|
|
35022
35138
|
mkdirSync as mkdirSync8,
|
|
35023
35139
|
readFileSync as readFileSync9,
|
|
35024
35140
|
renameSync as renameSync4,
|
|
@@ -35028,10 +35144,10 @@ import {
|
|
|
35028
35144
|
import { join as join19 } from "node:path";
|
|
35029
35145
|
|
|
35030
35146
|
// packages/cli/src/core/keyHelper.ts
|
|
35031
|
-
import { spawnSync as
|
|
35032
|
-
import { existsSync as
|
|
35033
|
-
import { dirname as
|
|
35034
|
-
var PACKAGED = { "darwin-arm64": "darwin", "darwin-x64": "darwin", "linux-x64": "linux-x64", "linux-arm64": "linux-arm64" };
|
|
35147
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
35148
|
+
import { existsSync as existsSync6, realpathSync as realpathSync2, statSync } from "node:fs";
|
|
35149
|
+
import { dirname as dirname8, isAbsolute as isAbsolute3, join as join18 } from "node:path";
|
|
35150
|
+
var PACKAGED = { "darwin-arm64": "darwin", "darwin-x64": "darwin", "linux-x64": "linux-x64", "linux-arm64": "linux-arm64", "win32-x64": "win32-x64", "win32-arm64": "win32-arm64" };
|
|
35035
35151
|
function chipOf(platform2) {
|
|
35036
35152
|
if (platform2 === "darwin") return "secure-enclave";
|
|
35037
35153
|
return platform2 === "linux" || platform2 === "win32" ? "tpm" : void 0;
|
|
@@ -35057,17 +35173,25 @@ var TPM_LIBRARIES_HINT = "\u041F\u043E\u0441\u0442\u0430\u0432\u044C\u0442\u0435
|
|
|
35057
35173
|
var LDD = "/usr/bin/ldd";
|
|
35058
35174
|
var LDD_TIMEOUT_MS = 5e3;
|
|
35059
35175
|
function missingLibraries(path2, platform2 = process.platform) {
|
|
35060
|
-
if (platform2 !== "linux" || !
|
|
35061
|
-
const result =
|
|
35176
|
+
if (platform2 !== "linux" || !existsSync6(LDD)) return [];
|
|
35177
|
+
const result = spawnSync3(LDD, [path2], { encoding: "utf8", timeout: LDD_TIMEOUT_MS, env: { PATH: "/usr/bin:/bin" } });
|
|
35062
35178
|
if (typeof result.stdout !== "string") return [];
|
|
35063
35179
|
return result.stdout.split("\n").filter((line) => line.includes("=> not found")).map((line) => line.trim().split(/\s+/)[0] ?? "").filter(Boolean);
|
|
35064
35180
|
}
|
|
35065
35181
|
var WRITABLE_BY_GROUP = 16;
|
|
35066
35182
|
var WRITABLE_BY_OTHERS = 2;
|
|
35067
35183
|
function isTrustedFile(path2) {
|
|
35184
|
+
if (process.platform === "win32") {
|
|
35185
|
+
try {
|
|
35186
|
+
assertWindowsHelperPath(path2);
|
|
35187
|
+
return true;
|
|
35188
|
+
} catch {
|
|
35189
|
+
return false;
|
|
35190
|
+
}
|
|
35191
|
+
}
|
|
35068
35192
|
const real = realpathSync2(path2);
|
|
35069
35193
|
const uid = process.getuid?.() ?? 0;
|
|
35070
|
-
return [real,
|
|
35194
|
+
return [real, dirname8(real)].every((p) => {
|
|
35071
35195
|
const st = statSync(p);
|
|
35072
35196
|
const groupOk = (st.mode & WRITABLE_BY_GROUP) === 0;
|
|
35073
35197
|
return (st.uid === uid || st.uid === 0) && (st.mode & WRITABLE_BY_OTHERS) === 0 && groupOk;
|
|
@@ -35079,9 +35203,9 @@ function unavailable(message2, hint) {
|
|
|
35079
35203
|
function findKeyHelper(opts) {
|
|
35080
35204
|
const path2 = opts.override ?? opts.installed;
|
|
35081
35205
|
if (!isAbsolute3(path2)) throw unavailable(`\u041F\u0443\u0442\u044C \u043A \u0445\u0435\u043B\u043F\u0435\u0440\u0443 ${path2} \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0430\u0431\u0441\u043E\u043B\u044E\u0442\u043D\u044B\u043C`, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043F\u043E\u043B\u043D\u044B\u0439 \u043F\u0443\u0442\u044C \u0432 SBERPAY_KEY_HELPER");
|
|
35082
|
-
if (!
|
|
35206
|
+
if (!existsSync6(path2)) return void 0;
|
|
35083
35207
|
if (!isTrustedFile(path2)) {
|
|
35084
|
-
throw unavailable(`\u0425\u0435\u043B\u043F\u0435\u0440 ${path2} \u043D\u0435 \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0438\u0442 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044E \u0438\u043B\u0438 \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u043D\u0430 \u0437\u0430\u043F\u0438\u0441\u044C \u0434\u0440\u0443\u0433\u0438\u043C`, "\u041F\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 sberpay-cli; \u043F\u0440\u0430\u0432\u0430 \u043D\u0430 \u0445\u0435\u043B\u043F\u0435\u0440 \u0438 \u0435\u0433\u043E \u043A\u0430\u0442\u0430\u043B\u043E\u0433 \u2014
|
|
35208
|
+
throw unavailable(`\u0425\u0435\u043B\u043F\u0435\u0440 ${path2} \u043D\u0435 \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0438\u0442 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044E \u0438\u043B\u0438 \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u043D\u0430 \u0437\u0430\u043F\u0438\u0441\u044C \u0434\u0440\u0443\u0433\u0438\u043C`, "\u041F\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 sberpay-cli; \u043F\u0440\u0430\u0432\u0430 \u043D\u0430 \u0445\u0435\u043B\u043F\u0435\u0440 \u0438 \u0435\u0433\u043E \u043A\u0430\u0442\u0430\u043B\u043E\u0433: Unix 0755; Windows \u2014 \u0437\u0430\u043F\u0438\u0441\u044C \u0442\u043E\u043B\u044C\u043A\u043E \u0432\u043B\u0430\u0434\u0435\u043B\u044C\u0446\u0443, SYSTEM \u0438 Administrators");
|
|
35085
35209
|
}
|
|
35086
35210
|
return path2;
|
|
35087
35211
|
}
|
|
@@ -35112,7 +35236,7 @@ function helperError(action2, error62, softwareAllowed) {
|
|
|
35112
35236
|
function osSecretStore(standName, stand, opts = {}) {
|
|
35113
35237
|
const { env = process.env, platform: platform2 = process.platform } = opts;
|
|
35114
35238
|
let secrets;
|
|
35115
|
-
const
|
|
35239
|
+
const open8 = () => {
|
|
35116
35240
|
if (secrets) return secrets;
|
|
35117
35241
|
const backend = keyHelperBackend(platform2);
|
|
35118
35242
|
if (!backend) throw keyringError(`\u041D\u0430 ${platform2} \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430 \u0441\u0435\u043A\u0440\u0435\u0442\u043E\u0432 \u041E\u0421 \u043D\u0435\u0442`, FILE_HINT);
|
|
@@ -35125,7 +35249,7 @@ function osSecretStore(standName, stand, opts = {}) {
|
|
|
35125
35249
|
return secrets;
|
|
35126
35250
|
};
|
|
35127
35251
|
const call = (action2, fn, name) => {
|
|
35128
|
-
const store =
|
|
35252
|
+
const store = open8();
|
|
35129
35253
|
try {
|
|
35130
35254
|
return fn(store, `${standName}:${name}`);
|
|
35131
35255
|
} catch (error62) {
|
|
@@ -35147,9 +35271,14 @@ function osSecretStore(standName, stand, opts = {}) {
|
|
|
35147
35271
|
}
|
|
35148
35272
|
function fileSecretStore(paths, stand) {
|
|
35149
35273
|
const file2 = join19(paths.configDir, `secrets.${stand}.json`);
|
|
35150
|
-
const read = () =>
|
|
35274
|
+
const read = () => {
|
|
35275
|
+
if (!existsSync7(file2)) return {};
|
|
35276
|
+
if (process.platform === "win32") assertWindowsPrivatePath(file2);
|
|
35277
|
+
return JSON.parse(readFileSync9(file2, "utf8"));
|
|
35278
|
+
};
|
|
35151
35279
|
const write = (data) => {
|
|
35152
|
-
|
|
35280
|
+
if (process.platform === "win32") ensureWindowsPrivateDirectory(paths.configDir);
|
|
35281
|
+
else mkdirSync8(paths.configDir, { recursive: true, mode: 448 });
|
|
35153
35282
|
if (Object.keys(data).length === 0) return rmSync5(file2, { force: true });
|
|
35154
35283
|
const tmp = `${file2}.${process.pid}.tmp`;
|
|
35155
35284
|
writeFileSync4(tmp, JSON.stringify(data), { mode: 384 });
|
|
@@ -35170,22 +35299,18 @@ function openSecretStore(paths, standName, stand, opts = {}) {
|
|
|
35170
35299
|
const env = opts.env ?? process.env;
|
|
35171
35300
|
if (env.SBERPAY_CLI_SECRETS !== "file")
|
|
35172
35301
|
return osSecretStore(standName, stand, opts);
|
|
35173
|
-
if (standName === "prod") {
|
|
35174
|
-
throw new CliError(
|
|
35175
|
-
EXIT.CONFIG_OR_NETWORK,
|
|
35176
|
-
"INSECURE_SECRETS",
|
|
35177
|
-
"\u041D\u0430 \u0441\u0442\u0435\u043D\u0434\u0435 prod \u0441\u0435\u043A\u0440\u0435\u0442\u044B \u0445\u0440\u0430\u043D\u044F\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u041E\u0421",
|
|
35178
|
-
{ hint: "\u0423\u0431\u0435\u0440\u0438\u0442\u0435 SBERPAY_CLI_SECRETS=file" }
|
|
35179
|
-
);
|
|
35180
|
-
}
|
|
35181
35302
|
return fileSecretStore(paths, standName);
|
|
35182
35303
|
}
|
|
35183
35304
|
|
|
35184
35305
|
// packages/cli/src/core/context.ts
|
|
35185
35306
|
var DEFAULT_LOGGING = join20(BUILD.root, "config", "logging.yaml");
|
|
35186
35307
|
function fileSink(paths, verbose) {
|
|
35187
|
-
|
|
35308
|
+
if (process.platform === "win32") ensureWindowsPrivateDirectory(paths.stateDir);
|
|
35309
|
+
else mkdirSync9(paths.stateDir, { recursive: true, mode: 448 });
|
|
35188
35310
|
const logFile = join20(paths.stateDir, "cli.log");
|
|
35311
|
+
if (process.platform === "win32") {
|
|
35312
|
+
if (existsSync8(logFile)) assertWindowsPrivatePath(logFile);
|
|
35313
|
+
}
|
|
35189
35314
|
return (line) => {
|
|
35190
35315
|
appendFileSync(logFile, `${line}
|
|
35191
35316
|
`, { mode: 384 });
|
|
@@ -35207,6 +35332,7 @@ function fileLogger(paths, verbose) {
|
|
|
35207
35332
|
function buildCoreContext(opts, overridePaths) {
|
|
35208
35333
|
const out = createOutput(Boolean(opts.json));
|
|
35209
35334
|
const paths = overridePaths ?? cliPaths();
|
|
35335
|
+
if (process.platform === "win32") for (const path2 of Object.values(paths)) ensureWindowsPrivateDirectory(path2);
|
|
35210
35336
|
const config2 = loadConfig(paths);
|
|
35211
35337
|
const requested = opts.stand ?? config2.stand;
|
|
35212
35338
|
if (!isStand(requested)) throw new CliError(EXIT.VALIDATION, "INVALID_ARGUMENT", `\u041D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439 \u0441\u0442\u0435\u043D\u0434 \xAB${requested}\xBB: ${STAND_NAMES.join(", ")}`);
|
|
@@ -35235,7 +35361,7 @@ function buildCoreContext(opts, overridePaths) {
|
|
|
35235
35361
|
}
|
|
35236
35362
|
|
|
35237
35363
|
// packages/cli/src/schemes/v2/deviceKeys.ts
|
|
35238
|
-
import { existsSync as
|
|
35364
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
35239
35365
|
import { join as join21 } from "node:path";
|
|
35240
35366
|
var DEVICE_SECRETS = ["deviceSignKey", "deviceEncKey"];
|
|
35241
35367
|
var SOFTWARE_ORDER = ["hardware", "os", "file"];
|
|
@@ -35267,12 +35393,13 @@ async function selectDeviceKeys(core, sel = {}) {
|
|
|
35267
35393
|
if (pref !== "auto" && !allowed.includes(pref)) {
|
|
35268
35394
|
throw unavailable2(
|
|
35269
35395
|
`\u0421\u0442\u0435\u043D\u0434 ${core.standName}: \u043A\u043B\u044E\u0447\u0438 \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u0430 \u0442\u043E\u043B\u044C\u043A\u043E \u0432 Secure Enclave \u0438\u043B\u0438 TPM, \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 ${pref} \u0437\u0430\u043F\u0440\u0435\u0449\u0435\u043D\u043E`,
|
|
35270
|
-
"\u0414\u043B\u044F \
|
|
35396
|
+
"\u0414\u043B\u044F \u0440\u0430\u0431\u043E\u0442\u044B \u0431\u0435\u0437 \u0447\u0438\u043F\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u0435 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u043D\u044B\u0435 \u043A\u043B\u044E\u0447\u0438: allowSoftwareKeys: true"
|
|
35271
35397
|
);
|
|
35272
35398
|
}
|
|
35273
35399
|
const backend = keyHelperBackend(platform2);
|
|
35274
35400
|
const hint = backend ? keyHelperBuildHint(backend) : `\u041D\u0430 ${platform2} \u0430\u043F\u043F\u0430\u0440\u0430\u0442\u043D\u044B\u0445 \u043A\u043B\u044E\u0447\u0435\u0439 \u043D\u0435\u0442`;
|
|
35275
35401
|
const hardwareFile = backend && hardwareKeyFile(core, backend.kind);
|
|
35402
|
+
if (process.platform === "win32" && hardwareFile && existsSync9(hardwareFile)) assertWindowsPrivatePath(hardwareFile);
|
|
35276
35403
|
let helperLookup;
|
|
35277
35404
|
const keyHelper = () => {
|
|
35278
35405
|
helperLookup ??= { path: backend && findKeyHelper({ override: overrides.SBERPAY_KEY_HELPER, installed: sel.installedHelper ?? backend.path }) };
|
|
@@ -35291,7 +35418,7 @@ async function selectDeviceKeys(core, sel = {}) {
|
|
|
35291
35418
|
const cached2 = probes.get(storage);
|
|
35292
35419
|
if (cached2) return cached2;
|
|
35293
35420
|
const result = (() => {
|
|
35294
|
-
if (storage === "hardware") return { ok: true, hasKeys: Boolean(hardwareFile &&
|
|
35421
|
+
if (storage === "hardware") return { ok: true, hasKeys: Boolean(hardwareFile && existsSync9(hardwareFile)) };
|
|
35295
35422
|
try {
|
|
35296
35423
|
return { ok: true, hasKeys: stores[storage]().get(SIGN_KEY_NAME) !== void 0 };
|
|
35297
35424
|
} catch {
|
|
@@ -35349,7 +35476,7 @@ async function selectDeviceKeys(core, sel = {}) {
|
|
|
35349
35476
|
throw unavailable2("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u041E\u0421 (keyring) \u043D\u0430 \u044D\u0442\u043E\u0439 \u043C\u0430\u0448\u0438\u043D\u0435 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E", "\u041D\u0430 \u043C\u0430\u0448\u0438\u043D\u0435 \u0431\u0435\u0437 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u043E\u0439 \u0441\u0435\u0441\u0441\u0438\u0438: sberpay-cli auth login --key-storage file");
|
|
35350
35477
|
throw unavailable2(
|
|
35351
35478
|
softwareAllowed ? "\u041D\u0435\u0442 \u043D\u0438 \u0447\u0438\u043F\u0430, \u043D\u0438 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430 \u043A\u043B\u044E\u0447\u0435\u0439" : `\u0421\u0442\u0435\u043D\u0434 ${core.standName}: \u043D\u0443\u0436\u0435\u043D \u043A\u043B\u044E\u0447 \u0432 Secure Enclave \u0438\u043B\u0438 TPM, \u0430 \u0447\u0438\u043F \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D`,
|
|
35352
|
-
softwareAllowed ? hint : `${hint}. \u0414\u043B\u044F \
|
|
35479
|
+
softwareAllowed ? hint : `${hint}. \u0414\u043B\u044F \u0440\u0430\u0431\u043E\u0442\u044B \u0431\u0435\u0437 \u0447\u0438\u043F\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u0435 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u043D\u044B\u0435 \u043A\u043B\u044E\u0447\u0438: allowSoftwareKeys: true`
|
|
35353
35480
|
);
|
|
35354
35481
|
}
|
|
35355
35482
|
async function keyHelperStatus(platform2 = process.platform, installedHelper) {
|
|
@@ -35369,11 +35496,11 @@ async function keyHelperStatus(platform2 = process.platform, installedHelper) {
|
|
|
35369
35496
|
}
|
|
35370
35497
|
function deviceKeysExist(core, platform2 = process.platform, env = process.env) {
|
|
35371
35498
|
const backend = keyHelperBackend(platform2);
|
|
35372
|
-
if (backend &&
|
|
35499
|
+
if (backend && existsSync9(hardwareKeyFile(core, backend.kind))) return true;
|
|
35373
35500
|
if (!core.stand.allowSoftwareKeys) return false;
|
|
35374
|
-
const has = (
|
|
35501
|
+
const has = (open8) => {
|
|
35375
35502
|
try {
|
|
35376
|
-
return
|
|
35503
|
+
return open8().get(SIGN_KEY_NAME) !== void 0;
|
|
35377
35504
|
} catch {
|
|
35378
35505
|
return false;
|
|
35379
35506
|
}
|
|
@@ -38229,7 +38356,7 @@ async function prepareBinding(ctx, mode) {
|
|
|
38229
38356
|
// packages/cli/src/schemes/v2/binding/launcher.ts
|
|
38230
38357
|
import { spawn as spawn3 } from "node:child_process";
|
|
38231
38358
|
import { openSync as openSync7, closeSync as closeSync7, mkdirSync as mkdirSync11 } from "node:fs";
|
|
38232
|
-
import { dirname as
|
|
38359
|
+
import { dirname as dirname9, join as join23 } from "node:path";
|
|
38233
38360
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
38234
38361
|
var Reply = external_exports.discriminatedUnion("type", [
|
|
38235
38362
|
external_exports.object({ type: external_exports.literal("READY"), generation: external_exports.string() }),
|
|
@@ -38238,8 +38365,8 @@ var Reply = external_exports.discriminatedUnion("type", [
|
|
|
38238
38365
|
]);
|
|
38239
38366
|
async function startLocalBinding(ctx, opts) {
|
|
38240
38367
|
const scope = bindingScope(ctx);
|
|
38241
|
-
const log = join23(
|
|
38242
|
-
mkdirSync11(
|
|
38368
|
+
const log = join23(dirname9(scope.recordPath), "worker.log");
|
|
38369
|
+
mkdirSync11(dirname9(log), { recursive: true, mode: 448 });
|
|
38243
38370
|
const fd2 = openSync7(log, "a", 384);
|
|
38244
38371
|
let child;
|
|
38245
38372
|
try {
|
|
@@ -38876,19 +39003,19 @@ function createScheme(core) {
|
|
|
38876
39003
|
}
|
|
38877
39004
|
|
|
38878
39005
|
// packages/cli/src/setup/command.ts
|
|
38879
|
-
import { spawnSync as
|
|
39006
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
38880
39007
|
import { createInterface } from "node:readline/promises";
|
|
38881
39008
|
|
|
38882
39009
|
// packages/cli/src/setup/collect.ts
|
|
38883
|
-
import { existsSync as
|
|
39010
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
38884
39011
|
import { homedir as homedir7 } from "node:os";
|
|
38885
39012
|
import { resolve as resolve5 } from "node:path";
|
|
38886
39013
|
|
|
38887
39014
|
// packages/cli/src/ca/rootCa.ts
|
|
38888
39015
|
import { randomBytes as randomBytes3, X509Certificate as X509Certificate2 } from "node:crypto";
|
|
38889
|
-
import { closeSync as closeSync8, existsSync as
|
|
39016
|
+
import { closeSync as closeSync8, existsSync as existsSync10, fchmodSync, lstatSync as lstatSync6, mkdirSync as mkdirSync12, mkdtempSync, openSync as openSync8, readFileSync as readFileSync12, renameSync as renameSync5, rmSync as rmSync7, writeFileSync as writeFileSync5, writeSync as writeSync4 } from "node:fs";
|
|
38890
39017
|
import { tmpdir } from "node:os";
|
|
38891
|
-
import { dirname as
|
|
39018
|
+
import { dirname as dirname10, join as join24, resolve as resolve3 } from "node:path";
|
|
38892
39019
|
var FETCH_TIMEOUT_MS = 15e3;
|
|
38893
39020
|
var LOGIN_KEYCHAIN = "Library/Keychains/login.keychain-db";
|
|
38894
39021
|
var SECURITY_BIN = "/usr/bin/security";
|
|
@@ -38920,11 +39047,11 @@ function verifyRootCert(data, root, now = /* @__PURE__ */ new Date()) {
|
|
|
38920
39047
|
}
|
|
38921
39048
|
function readFetchedRoot(paths, root = RUSSIAN_TRUSTED_ROOT_CA) {
|
|
38922
39049
|
const file2 = rootCaFile(paths, root);
|
|
38923
|
-
return
|
|
39050
|
+
return existsSync10(file2) ? verifyRootCert(readFileSync12(file2), root) : void 0;
|
|
38924
39051
|
}
|
|
38925
39052
|
function ensureCaDir(dir2) {
|
|
38926
39053
|
mkdirSync12(dir2, { recursive: true, mode: 448 });
|
|
38927
|
-
const stat4 =
|
|
39054
|
+
const stat4 = lstatSync6(dir2);
|
|
38928
39055
|
const foreign = typeof process.getuid === "function" && stat4.uid !== process.getuid();
|
|
38929
39056
|
if (stat4.isSymbolicLink() || !stat4.isDirectory() || foreign) {
|
|
38930
39057
|
throw new CliError(EXIT.CONFIG_OR_NETWORK, "CA_DIR_UNSAFE", `${dir2} \u2014 \u043D\u0435 \u0441\u0432\u043E\u0439 \u043A\u0430\u0442\u0430\u043B\u043E\u0433 (\u0441\u0438\u043C\u043B\u0438\u043D\u043A \u0438\u043B\u0438 \u0447\u0443\u0436\u043E\u0439 \u0432\u043B\u0430\u0434\u0435\u043B\u0435\u0446): \u0444\u0430\u0439\u043B \u043A\u043E\u0440\u043D\u044F \u0442\u0443\u0434\u0430 \u043D\u0435 \u043F\u0438\u0448\u0435\u043C`, {
|
|
@@ -38933,7 +39060,7 @@ function ensureCaDir(dir2) {
|
|
|
38933
39060
|
}
|
|
38934
39061
|
}
|
|
38935
39062
|
function writeAtomically(path2, data, mode) {
|
|
38936
|
-
const tmp = join24(
|
|
39063
|
+
const tmp = join24(dirname10(path2), `.${randomBytes3(6).toString("hex")}.tmp`);
|
|
38937
39064
|
const fd2 = openSync8(tmp, "wx", mode);
|
|
38938
39065
|
try {
|
|
38939
39066
|
fchmodSync(fd2, mode);
|
|
@@ -38953,7 +39080,7 @@ async function fetchRootCa(deps) {
|
|
|
38953
39080
|
const data = await callBytes(deps.logger, { op: `\u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u0435 \u043A\u043E\u0440\u043D\u044F ${root.name}`, peer: "\u0413\u043E\u0441\u0443\u0441\u043B\u0443\u0433\u0438", url: root.sourceUrl, timeoutMs: FETCH_TIMEOUT_MS });
|
|
38954
39081
|
const cert = verifyRootCert(data, root);
|
|
38955
39082
|
const path2 = rootCaFile(deps.paths, root);
|
|
38956
|
-
ensureCaDir(
|
|
39083
|
+
ensureCaDir(dirname10(path2));
|
|
38957
39084
|
writeAtomically(path2, cert.toString(), 420);
|
|
38958
39085
|
return { path: path2, jwkThumbprint: root.jwkThumbprint, fingerprint256: cert.fingerprint256, validTo: new Date(cert.validTo).toISOString(), sourceUrl: root.sourceUrl };
|
|
38959
39086
|
}
|
|
@@ -39033,9 +39160,9 @@ function installRootCa(deps) {
|
|
|
39033
39160
|
|
|
39034
39161
|
// packages/cli/src/setup/skill.ts
|
|
39035
39162
|
import { createHash as createHash16 } from "node:crypto";
|
|
39036
|
-
import { cpSync, existsSync as
|
|
39163
|
+
import { cpSync, existsSync as existsSync11, lstatSync as lstatSync7, mkdirSync as mkdirSync13, readdirSync as readdirSync3, readFileSync as readFileSync13, readlinkSync, realpathSync as realpathSync3, renameSync as renameSync6, rmSync as rmSync8, statSync as statSync2, symlinkSync, writeFileSync as writeFileSync6 } from "node:fs";
|
|
39037
39164
|
import { homedir as homedir6 } from "node:os";
|
|
39038
|
-
import { basename, dirname as
|
|
39165
|
+
import { basename, dirname as dirname11, join as join25, relative as relative3, resolve as resolve4 } from "node:path";
|
|
39039
39166
|
var SKILL_NAME = "sberpay";
|
|
39040
39167
|
var MANIFEST = ".sberpay-cli.json";
|
|
39041
39168
|
var WORK_DIR = ".sberpay-cli";
|
|
@@ -39068,14 +39195,14 @@ function sameDir(a, b) {
|
|
|
39068
39195
|
}
|
|
39069
39196
|
function isLink(path2) {
|
|
39070
39197
|
try {
|
|
39071
|
-
return
|
|
39198
|
+
return lstatSync7(path2).isSymbolicLink();
|
|
39072
39199
|
} catch {
|
|
39073
39200
|
return false;
|
|
39074
39201
|
}
|
|
39075
39202
|
}
|
|
39076
39203
|
function readManifest(target) {
|
|
39077
39204
|
const file2 = join25(target, MANIFEST);
|
|
39078
|
-
if (!
|
|
39205
|
+
if (!existsSync11(file2)) return void 0;
|
|
39079
39206
|
try {
|
|
39080
39207
|
const data = JSON.parse(readFileSync13(file2, "utf8"));
|
|
39081
39208
|
return typeof data.version === "string" && data.files && typeof data.files === "object" ? data : void 0;
|
|
@@ -39083,13 +39210,13 @@ function readManifest(target) {
|
|
|
39083
39210
|
return void 0;
|
|
39084
39211
|
}
|
|
39085
39212
|
}
|
|
39086
|
-
var isStaleOwnLink = (target) => !
|
|
39213
|
+
var isStaleOwnLink = (target) => !existsSync11(target) && readlinkSync(target).replace(/[\\/]+$/, "").endsWith(join25("skill", SKILL_NAME));
|
|
39087
39214
|
function inspectSkill(source, target) {
|
|
39088
39215
|
if (isLink(target)) {
|
|
39089
|
-
if (
|
|
39216
|
+
if (existsSync11(target)) return sameDir(target, source) ? { state: "current", mode: "link" } : { state: "foreign" };
|
|
39090
39217
|
return isStaleOwnLink(target) ? { state: "outdated", mode: "link" } : { state: "foreign" };
|
|
39091
39218
|
}
|
|
39092
|
-
if (!
|
|
39219
|
+
if (!existsSync11(target)) return { state: "missing" };
|
|
39093
39220
|
const manifest = readManifest(target);
|
|
39094
39221
|
if (!manifest) return { state: "foreign" };
|
|
39095
39222
|
if (!sameFiles(hashFiles(target), manifest.files)) return { state: "modified", mode: "copy" };
|
|
@@ -39109,7 +39236,7 @@ function prepare(source, work, mode, version2) {
|
|
|
39109
39236
|
return fresh;
|
|
39110
39237
|
}
|
|
39111
39238
|
function swap(fresh, target, aside, work) {
|
|
39112
|
-
const previous =
|
|
39239
|
+
const previous = existsSync11(target) || isLink(target) ? aside ?? join25(work, `old-${process.pid}`) : void 0;
|
|
39113
39240
|
if (previous) renameSync6(target, previous);
|
|
39114
39241
|
try {
|
|
39115
39242
|
renameSync6(fresh, target);
|
|
@@ -39129,7 +39256,7 @@ function installSkill(source, target, opts) {
|
|
|
39129
39256
|
hint: "\u041F\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C: sberpay-cli setup --force-skill \u2014 \u043F\u0440\u0435\u0436\u043D\u0438\u0439 \u043A\u0430\u0442\u0430\u043B\u043E\u0433 \u0443\u0439\u0434\u0451\u0442 \u0432 \u0431\u044D\u043A\u0430\u043F"
|
|
39130
39257
|
});
|
|
39131
39258
|
}
|
|
39132
|
-
const work = join25(
|
|
39259
|
+
const work = join25(dirname11(target), WORK_DIR);
|
|
39133
39260
|
mkdirSync13(work, { recursive: true });
|
|
39134
39261
|
const backup = ours ? void 0 : join25(work, `backup-${basename(target)}-${(opts.now ?? /* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`);
|
|
39135
39262
|
const fresh = prepare(source, work, opts.mode, opts.version);
|
|
@@ -39511,7 +39638,7 @@ function rootStep(stand, paths, root) {
|
|
|
39511
39638
|
platform: process.platform,
|
|
39512
39639
|
file: rootCaFile(paths, root),
|
|
39513
39640
|
home: homedir7(),
|
|
39514
|
-
exists:
|
|
39641
|
+
exists: existsSync12,
|
|
39515
39642
|
cert
|
|
39516
39643
|
});
|
|
39517
39644
|
return rootCaStep({
|
|
@@ -39608,10 +39735,10 @@ function run2(argv) {
|
|
|
39608
39735
|
const self = process.argv[1];
|
|
39609
39736
|
if (!head || head === "sberpay-cli" && !self) return false;
|
|
39610
39737
|
const nested = head === "sberpay-cli" && rest.includes("setup");
|
|
39611
|
-
const result = head === "sberpay-cli" ?
|
|
39738
|
+
const result = head === "sberpay-cli" ? spawnSync4(process.execPath, [...process.execArgv, self, ...rest, ...nested ? ["--yes", "--json"] : []], {
|
|
39612
39739
|
stdio: nested ? ["inherit", "pipe", "inherit"] : "inherit",
|
|
39613
39740
|
encoding: "utf8"
|
|
39614
|
-
}) :
|
|
39741
|
+
}) : spawnSync4(head, rest, { stdio: "inherit", cwd: BUILD.root, shell: process.platform === "win32" });
|
|
39615
39742
|
if (result.error) process.stderr.write(`\u2717 \u041D\u0435 \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u043B\u043E\u0441\u044C ${argv.join(" ")}: ${result.error.message}
|
|
39616
39743
|
`);
|
|
39617
39744
|
if (nested && typeof result.stdout === "string") reportNestedError(result.stdout);
|
|
@@ -39665,14 +39792,14 @@ async function setupCommand(globals, opts) {
|
|
|
39665
39792
|
}
|
|
39666
39793
|
|
|
39667
39794
|
// packages/cli/src/ca/command.ts
|
|
39668
|
-
import { spawnSync as
|
|
39669
|
-
import { existsSync as
|
|
39795
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
39796
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
39670
39797
|
import { homedir as homedir8 } from "node:os";
|
|
39671
39798
|
var INSTALL_TIMEOUT_MS = 12e4;
|
|
39672
39799
|
var WHERE = { system: "\u0432 \u0434\u043E\u0432\u0435\u0440\u0435\u043D\u043D\u044B\u0445 \u043A\u043E\u0440\u043D\u044F\u0445 \u0441\u0438\u0441\u0442\u0435\u043C\u044B", extra: "\u0438\u0437 NODE_EXTRA_CA_CERTS (\u0441\u0438\u0441\u0442\u0435\u043C\u0430 \u0435\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0435\u0442)" };
|
|
39673
39800
|
function runSecurity(argv) {
|
|
39674
39801
|
const [head = "", ...rest] = argv;
|
|
39675
|
-
const result =
|
|
39802
|
+
const result = spawnSync5(head, rest, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: INSTALL_TIMEOUT_MS });
|
|
39676
39803
|
return { status: result.status, stderr: result.error ? result.error.message : result.stderr };
|
|
39677
39804
|
}
|
|
39678
39805
|
function caStatusCommand(globals) {
|
|
@@ -39707,7 +39834,7 @@ async function caFetchCommand(globals) {
|
|
|
39707
39834
|
function caInstallCommand(globals) {
|
|
39708
39835
|
const out = createOutput(Boolean(globals.json));
|
|
39709
39836
|
out.progress("\u0414\u043E\u0431\u0430\u0432\u043B\u044F\u044E \u043A\u043E\u0440\u0435\u043D\u044C \u0432 \u0434\u043E\u0432\u0435\u0440\u0435\u043D\u043D\u044B\u0435 \u043A\u043E\u0440\u043D\u0438 \u0441\u0438\u0441\u0442\u0435\u043C\u044B \u2014 \u0441\u0438\u0441\u0442\u0435\u043C\u0430 \u043C\u043E\u0436\u0435\u0442 \u0441\u043F\u0440\u043E\u0441\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C\u2026");
|
|
39710
|
-
const result = installRootCa({ paths: cliPaths(), platform: process.platform, home: homedir8(), exists:
|
|
39837
|
+
const result = installRootCa({ paths: cliPaths(), platform: process.platform, home: homedir8(), exists: existsSync13, run: runSecurity });
|
|
39711
39838
|
const human = result.installed ? `\u2713 ${result.say}` : [`\u041A\u043E\u043C\u0430\u043D\u0434\u0443 \u0432\u044B\u043F\u043E\u043B\u043D\u044F\u0435\u0442 \u0447\u0435\u043B\u043E\u0432\u0435\u043A: ${result.command ?? "\u2014"}`, ` ${result.say}`].join("\n");
|
|
39712
39839
|
out.result(result, human);
|
|
39713
39840
|
}
|