@pretense/cli 0.6.19 → 0.6.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-XY4NRTOT.js → chunk-2BMR5XBU.js} +1 -1
- package/dist/index.js +348 -101
- package/dist/postinstall.js +1 -1
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ function versionFromPackageJson() {
|
|
|
17
17
|
return void 0;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
var PRETENSE_VERSION = (true ? "0.6.
|
|
20
|
+
var PRETENSE_VERSION = (true ? "0.6.21" : void 0) ?? versionFromPackageJson() ?? "0.0.0-unknown";
|
|
21
21
|
|
|
22
22
|
export {
|
|
23
23
|
PRETENSE_VERSION
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
PRETENSE_VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2BMR5XBU.js";
|
|
5
5
|
import {
|
|
6
6
|
__commonJS,
|
|
7
7
|
__toESM,
|
|
@@ -14472,14 +14472,16 @@ async function scanWithPresidio(text, presidioUrl, opts = {}) {
|
|
|
14472
14472
|
|
|
14473
14473
|
// ../packages/mutator/dist/index.js
|
|
14474
14474
|
init_esm_shims();
|
|
14475
|
+
import { existsSync as existsSync4, readFileSync as readFileSync32 } from "fs";
|
|
14476
|
+
import { join as join4 } from "path";
|
|
14475
14477
|
import { createHmac, hkdfSync, randomBytes as randomBytes2 } from "crypto";
|
|
14476
14478
|
import { createHash, randomBytes } from "crypto";
|
|
14477
14479
|
import { readFileSync as readFileSync4, existsSync as existsSync22 } from "fs";
|
|
14478
14480
|
import { homedir as homedir2 } from "os";
|
|
14479
14481
|
import { join as join22, dirname, parse, resolve } from "path";
|
|
14480
|
-
import { chmodSync, existsSync as
|
|
14482
|
+
import { chmodSync, existsSync as existsSync5, mkdirSync as mkdirSync2, statSync, writeFileSync as writeFileSync3 } from "fs";
|
|
14481
14483
|
import { homedir } from "os";
|
|
14482
|
-
import { join as
|
|
14484
|
+
import { join as join5 } from "path";
|
|
14483
14485
|
var DIR_MODE = 448;
|
|
14484
14486
|
var FILE_MODE = 384;
|
|
14485
14487
|
var POSIX_MODES_ENFORCED = process.platform !== "win32";
|
|
@@ -14501,10 +14503,10 @@ var PretenseHomeError = class extends Error {
|
|
|
14501
14503
|
}
|
|
14502
14504
|
};
|
|
14503
14505
|
function pretenseHome() {
|
|
14504
|
-
return
|
|
14506
|
+
return join5(homedir(), ".pretense");
|
|
14505
14507
|
}
|
|
14506
14508
|
function ensureDirOwnerOnly(dir) {
|
|
14507
|
-
const preExisting =
|
|
14509
|
+
const preExisting = existsSync5(dir);
|
|
14508
14510
|
if (!preExisting) {
|
|
14509
14511
|
try {
|
|
14510
14512
|
mkdirSync2(dir, { recursive: true, mode: DIR_MODE });
|
|
@@ -15634,6 +15636,79 @@ function mutate(code, language, seed = "pretense", opts = {}) {
|
|
|
15634
15636
|
}
|
|
15635
15637
|
};
|
|
15636
15638
|
}
|
|
15639
|
+
function mutateNamedIdentifiers(code, language, identifiers, seed = "pretense", opts = {}) {
|
|
15640
|
+
const t0 = performance.now();
|
|
15641
|
+
const lang = language ?? detectLanguage(code);
|
|
15642
|
+
const map = /* @__PURE__ */ new Map();
|
|
15643
|
+
if (!code?.trim() || identifiers.length === 0) {
|
|
15644
|
+
return { mutatedCode: code ?? "", map, stats: { tokensScanned: identifiers.length, tokensMutated: 0, durationMs: 0, language: lang } };
|
|
15645
|
+
}
|
|
15646
|
+
const signingKey = resolveSigningKey(opts);
|
|
15647
|
+
const usedSynthetics = /* @__PURE__ */ new Set();
|
|
15648
|
+
for (const { name, category } of identifiers) {
|
|
15649
|
+
if (!name || name.length <= 1 || SKIP_IDENTIFIERS2.has(name)) continue;
|
|
15650
|
+
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name)) continue;
|
|
15651
|
+
if (map.has(name)) continue;
|
|
15652
|
+
let synthetic = generateSyntheticName(name, seed, category, signingKey);
|
|
15653
|
+
let attempt = 0;
|
|
15654
|
+
while ((usedSynthetics.has(synthetic) || synthetic === name || code.includes(synthetic)) && attempt < 100) {
|
|
15655
|
+
attempt++;
|
|
15656
|
+
synthetic = generateSyntheticName(name, `${seed}:${attempt}`, category, signingKey);
|
|
15657
|
+
}
|
|
15658
|
+
if (synthetic !== name && !usedSynthetics.has(synthetic) && !code.includes(synthetic)) {
|
|
15659
|
+
map.set(name, synthetic);
|
|
15660
|
+
usedSynthetics.add(synthetic);
|
|
15661
|
+
}
|
|
15662
|
+
}
|
|
15663
|
+
const entries = [...map.entries()].sort((a, b) => b[0].length - a[0].length);
|
|
15664
|
+
let mutatedCode = code;
|
|
15665
|
+
const applied = /* @__PURE__ */ new Map();
|
|
15666
|
+
for (const [original, synthetic] of entries) {
|
|
15667
|
+
const next = replaceAll(mutatedCode, [[original, synthetic]], lang, true);
|
|
15668
|
+
if (next !== mutatedCode) {
|
|
15669
|
+
applied.set(original, synthetic);
|
|
15670
|
+
mutatedCode = next;
|
|
15671
|
+
}
|
|
15672
|
+
}
|
|
15673
|
+
return {
|
|
15674
|
+
mutatedCode,
|
|
15675
|
+
map: applied,
|
|
15676
|
+
stats: {
|
|
15677
|
+
tokensScanned: identifiers.length,
|
|
15678
|
+
tokensMutated: applied.size,
|
|
15679
|
+
durationMs: Math.round((performance.now() - t0) * 100) / 100,
|
|
15680
|
+
language: lang
|
|
15681
|
+
}
|
|
15682
|
+
};
|
|
15683
|
+
}
|
|
15684
|
+
var FINGERPRINT_CATEGORIES = [
|
|
15685
|
+
["functions", "function"],
|
|
15686
|
+
["classes", "class"],
|
|
15687
|
+
["constants", "constant"],
|
|
15688
|
+
["envVars", "variable"]
|
|
15689
|
+
];
|
|
15690
|
+
function loadFingerprintIdentifiers(projectRoot) {
|
|
15691
|
+
const path2 = join4(projectRoot, ".pretense", "fingerprint.json");
|
|
15692
|
+
if (!existsSync4(path2)) return [];
|
|
15693
|
+
let parsed;
|
|
15694
|
+
try {
|
|
15695
|
+
parsed = JSON.parse(readFileSync32(path2, "utf-8"));
|
|
15696
|
+
} catch {
|
|
15697
|
+
return [];
|
|
15698
|
+
}
|
|
15699
|
+
const out = [];
|
|
15700
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15701
|
+
for (const [key, category] of FINGERPRINT_CATEGORIES) {
|
|
15702
|
+
const arr = parsed[key];
|
|
15703
|
+
if (!Array.isArray(arr)) continue;
|
|
15704
|
+
for (const name of arr) {
|
|
15705
|
+
if (typeof name !== "string" || seen.has(name)) continue;
|
|
15706
|
+
seen.add(name);
|
|
15707
|
+
out.push({ name, category });
|
|
15708
|
+
}
|
|
15709
|
+
}
|
|
15710
|
+
return out;
|
|
15711
|
+
}
|
|
15637
15712
|
function reverse(mutatedCode, map) {
|
|
15638
15713
|
if (!mutatedCode || map.size === 0) return mutatedCode;
|
|
15639
15714
|
assertNoReplacementCollision(map.entries());
|
|
@@ -15940,7 +16015,7 @@ var RiskScorer = class {
|
|
|
15940
16015
|
// ../packages/store/dist/index.js
|
|
15941
16016
|
init_esm_shims();
|
|
15942
16017
|
import { createRequire as createRequire2 } from "module";
|
|
15943
|
-
import { mkdirSync as mkdirSync22, existsSync as
|
|
16018
|
+
import { mkdirSync as mkdirSync22, existsSync as existsSync6, chmodSync as chmodSync2, statSync as statSync2 } from "fs";
|
|
15944
16019
|
import { dirname as dirname2 } from "path";
|
|
15945
16020
|
import { homedir as homedir22 } from "os";
|
|
15946
16021
|
var nodeRequire = createRequire2(import.meta.url);
|
|
@@ -16001,7 +16076,7 @@ function openDatabase(path2) {
|
|
|
16001
16076
|
return sqliteBackend === "bun:sqlite" ? openBun(path2) : openBetterSqlite3(path2);
|
|
16002
16077
|
}
|
|
16003
16078
|
function ensureDbDirOwnerOnly(dir) {
|
|
16004
|
-
const preExisting =
|
|
16079
|
+
const preExisting = existsSync6(dir);
|
|
16005
16080
|
if (!preExisting) mkdirSync22(dir, { recursive: true, mode: 448 });
|
|
16006
16081
|
if (process.platform === "win32") return;
|
|
16007
16082
|
try {
|
|
@@ -16051,7 +16126,7 @@ var AuditStore = class {
|
|
|
16051
16126
|
if (!isMemory) {
|
|
16052
16127
|
for (const p of [resolvedPath, `${resolvedPath}-wal`, `${resolvedPath}-shm`]) {
|
|
16053
16128
|
try {
|
|
16054
|
-
if (
|
|
16129
|
+
if (existsSync6(p)) chmodSync2(p, 384);
|
|
16055
16130
|
} catch {
|
|
16056
16131
|
}
|
|
16057
16132
|
}
|
|
@@ -16432,8 +16507,8 @@ var PERIOD_DAYS = 7;
|
|
|
16432
16507
|
var PERIOD_MS = PERIOD_DAYS * 24 * 60 * 60 * 1e3;
|
|
16433
16508
|
|
|
16434
16509
|
// ../apps/proxy/dist/server.js
|
|
16435
|
-
import { readFileSync as readFileSync5, existsSync as
|
|
16436
|
-
import { join as
|
|
16510
|
+
import { readFileSync as readFileSync5, existsSync as existsSync7 } from "fs";
|
|
16511
|
+
import { join as join6 } from "path";
|
|
16437
16512
|
import { parse as parseYaml } from "yaml";
|
|
16438
16513
|
import { readFileSync as readFileSync23 } from "fs";
|
|
16439
16514
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -16531,12 +16606,12 @@ var DEFAULTS = {
|
|
|
16531
16606
|
};
|
|
16532
16607
|
function loadConfig(configPath) {
|
|
16533
16608
|
const paths = configPath ? [configPath] : [
|
|
16534
|
-
|
|
16535
|
-
|
|
16536
|
-
|
|
16609
|
+
join6(process.cwd(), "pretense.yaml"),
|
|
16610
|
+
join6(process.cwd(), "pretense.yml"),
|
|
16611
|
+
join6(process.env["HOME"] ?? "/tmp", ".pretense", "config.yaml")
|
|
16537
16612
|
];
|
|
16538
16613
|
for (const p of paths) {
|
|
16539
|
-
if (
|
|
16614
|
+
if (existsSync7(p)) {
|
|
16540
16615
|
try {
|
|
16541
16616
|
const raw2 = parseYaml(readFileSync5(p, "utf-8"));
|
|
16542
16617
|
return deepMerge(DEFAULTS, raw2);
|
|
@@ -16582,11 +16657,11 @@ function versionFromCliPackageJson() {
|
|
|
16582
16657
|
return void 0;
|
|
16583
16658
|
}
|
|
16584
16659
|
function productVersion() {
|
|
16585
|
-
return override ?? (true ? "0.6.
|
|
16660
|
+
return override ?? (true ? "0.6.21" : void 0) ?? versionFromCliPackageJson() ?? "0.0.0-unknown";
|
|
16586
16661
|
}
|
|
16587
16662
|
var UNKNOWN_COMMIT = "unknown";
|
|
16588
16663
|
function bakedCommitSha() {
|
|
16589
|
-
return "
|
|
16664
|
+
return "7e80103647b573f455a73aecebeae1a0e2fa3ac9".length > 0 ? "7e80103647b573f455a73aecebeae1a0e2fa3ac9" : UNKNOWN_COMMIT;
|
|
16590
16665
|
}
|
|
16591
16666
|
var FEATURE_TIERS = {
|
|
16592
16667
|
compliance_export: "pro",
|
|
@@ -17201,6 +17276,65 @@ function getTelemetryEmitter(dashboardUrl, pushToken) {
|
|
|
17201
17276
|
_emitter = new TelemetryEmitter(url, token);
|
|
17202
17277
|
return _emitter;
|
|
17203
17278
|
}
|
|
17279
|
+
var DEFAULT_UPLOAD_URL = "https://api.pretense.ai";
|
|
17280
|
+
var UPLOAD_TIMEOUT_MS = 5e3;
|
|
17281
|
+
var MAX_IN_FLIGHT2 = 64;
|
|
17282
|
+
var _inFlight = 0;
|
|
17283
|
+
var _dropped = 0;
|
|
17284
|
+
function telemetryDisabled() {
|
|
17285
|
+
const v = process.env["PRETENSE_NO_TELEMETRY"]?.trim().toLowerCase();
|
|
17286
|
+
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
17287
|
+
}
|
|
17288
|
+
function resolveUploadBaseUrl() {
|
|
17289
|
+
const raw2 = (process.env["PRETENSE_DASHBOARD_URL"] ?? DEFAULT_UPLOAD_URL).trim();
|
|
17290
|
+
if (!raw2) return DEFAULT_UPLOAD_URL;
|
|
17291
|
+
const normalized = /^https?:\/\//i.test(raw2) ? raw2 : `https://${raw2}`;
|
|
17292
|
+
try {
|
|
17293
|
+
const u = new URL(normalized);
|
|
17294
|
+
const path2 = u.pathname === "/" ? "" : u.pathname.replace(/\/$/, "");
|
|
17295
|
+
return `${u.origin}${path2}`;
|
|
17296
|
+
} catch {
|
|
17297
|
+
return DEFAULT_UPLOAD_URL;
|
|
17298
|
+
}
|
|
17299
|
+
}
|
|
17300
|
+
function resolveUploadKey(requestKey) {
|
|
17301
|
+
const dashboardKey = process.env["PRETENSE_DASHBOARD_API_KEY"]?.trim();
|
|
17302
|
+
if (dashboardKey) return dashboardKey;
|
|
17303
|
+
const rk = requestKey?.trim();
|
|
17304
|
+
return rk && rk.length > 0 ? rk : null;
|
|
17305
|
+
}
|
|
17306
|
+
function clampCount(n) {
|
|
17307
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
|
|
17308
|
+
}
|
|
17309
|
+
function uploadProxyUsage(event) {
|
|
17310
|
+
if (telemetryDisabled()) return;
|
|
17311
|
+
const key = resolveUploadKey(event.apiKey);
|
|
17312
|
+
if (!key) return;
|
|
17313
|
+
if (_inFlight >= MAX_IN_FLIGHT2) {
|
|
17314
|
+
_dropped++;
|
|
17315
|
+
return;
|
|
17316
|
+
}
|
|
17317
|
+
const url = `${resolveUploadBaseUrl()}/api/cli/log`;
|
|
17318
|
+
const signal = typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(UPLOAD_TIMEOUT_MS) : void 0;
|
|
17319
|
+
_inFlight++;
|
|
17320
|
+
void Promise.resolve().then(
|
|
17321
|
+
() => fetch(url, {
|
|
17322
|
+
method: "POST",
|
|
17323
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${key}` },
|
|
17324
|
+
// COUNTS + METADATA ONLY — never a secret value or request body.
|
|
17325
|
+
body: JSON.stringify({
|
|
17326
|
+
file_count: 0,
|
|
17327
|
+
identifiers_mutated: clampCount(event.identifiersMutated),
|
|
17328
|
+
secrets_blocked: clampCount(event.secretsBlocked),
|
|
17329
|
+
llm_provider: event.provider
|
|
17330
|
+
}),
|
|
17331
|
+
...signal ? { signal } : {}
|
|
17332
|
+
})
|
|
17333
|
+
).catch(() => {
|
|
17334
|
+
}).finally(() => {
|
|
17335
|
+
_inFlight--;
|
|
17336
|
+
});
|
|
17337
|
+
}
|
|
17204
17338
|
var riskScorer = new RiskScorer();
|
|
17205
17339
|
function detectUpstream(path2, overrideHeader) {
|
|
17206
17340
|
if (overrideHeader) return overrideHeader;
|
|
@@ -17532,6 +17666,7 @@ function createProxy(opts = {}) {
|
|
|
17532
17666
|
}
|
|
17533
17667
|
const app = new Hono2();
|
|
17534
17668
|
const derivation = { projectRoot: resolveProxyProjectRoot(opts.projectRoot) };
|
|
17669
|
+
const fingerprintIdentifiers = loadFingerprintIdentifiers(derivation.projectRoot);
|
|
17535
17670
|
let auditWriteFailures = 0;
|
|
17536
17671
|
let auditWriteFailureLogged = false;
|
|
17537
17672
|
const safeLog = (entry) => {
|
|
@@ -17899,9 +18034,16 @@ ${_upgradeTier === "enterprise" ? "Enterprise offers unlimited mutations \u2014
|
|
|
17899
18034
|
continue;
|
|
17900
18035
|
}
|
|
17901
18036
|
const result = mutate(block.code, block.language, "pretense", derivation);
|
|
18037
|
+
let blockCode = result.mutatedCode;
|
|
17902
18038
|
for (const [k, v] of result.map.entries()) globalMap.set(k, v);
|
|
17903
18039
|
tokensMutated += result.stats.tokensMutated;
|
|
17904
|
-
|
|
18040
|
+
if (fingerprintIdentifiers.length > 0) {
|
|
18041
|
+
const fp = mutateNamedIdentifiers(blockCode, block.language, fingerprintIdentifiers, "pretense", derivation);
|
|
18042
|
+
for (const [k, v] of fp.map.entries()) globalMap.set(k, v);
|
|
18043
|
+
tokensMutated += fp.stats.tokensMutated;
|
|
18044
|
+
blockCode = fp.mutatedCode;
|
|
18045
|
+
}
|
|
18046
|
+
mutatedBlocks.push(blockCode);
|
|
17905
18047
|
}
|
|
17906
18048
|
return replaceCodeBlocks(text, blocks, mutatedBlocks);
|
|
17907
18049
|
});
|
|
@@ -18076,6 +18218,15 @@ ${_upgradeTier === "enterprise" ? "Enterprise offers unlimited mutations \u2014
|
|
|
18076
18218
|
...skippedUnscannable > 0 ? { findings: ["skipped_unscannable_field"] } : {},
|
|
18077
18219
|
sourceIp: c.req.header("x-forwarded-for") ?? c.req.header("x-real-ip")
|
|
18078
18220
|
}));
|
|
18221
|
+
if (anyTokenized) {
|
|
18222
|
+
const usageKey = c.req.header("x-pretense-api-key") ?? c.req.header("authorization")?.replace(/^Bearer\s+/i, "");
|
|
18223
|
+
uploadProxyUsage({
|
|
18224
|
+
apiKey: usageKey,
|
|
18225
|
+
identifiersMutated: mutationsApplied,
|
|
18226
|
+
secretsBlocked: secretsTokenized,
|
|
18227
|
+
provider
|
|
18228
|
+
});
|
|
18229
|
+
}
|
|
18079
18230
|
const reverseMap = /* @__PURE__ */ new Map();
|
|
18080
18231
|
for (const [orig, syn] of globalMap.entries()) {
|
|
18081
18232
|
if (!secretMap.has(syn)) reverseMap.set(orig, syn);
|
|
@@ -18195,11 +18346,11 @@ async function findFreePort(start, opts = {}) {
|
|
|
18195
18346
|
|
|
18196
18347
|
// src/proxy-pidfile.ts
|
|
18197
18348
|
init_esm_shims();
|
|
18198
|
-
import { existsSync as
|
|
18199
|
-
import { join as
|
|
18349
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, unlinkSync } from "fs";
|
|
18350
|
+
import { join as join7 } from "path";
|
|
18200
18351
|
import { homedir as homedir3 } from "os";
|
|
18201
18352
|
function pidFilePath(home = homedir3()) {
|
|
18202
|
-
return
|
|
18353
|
+
return join7(process.env.PRETENSE_PID_DIR ?? join7(home, ".pretense"), "proxy.pid");
|
|
18203
18354
|
}
|
|
18204
18355
|
function isProcessAlive(pid) {
|
|
18205
18356
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -18211,7 +18362,7 @@ function isProcessAlive(pid) {
|
|
|
18211
18362
|
}
|
|
18212
18363
|
}
|
|
18213
18364
|
function readProxyRecord(path2 = pidFilePath()) {
|
|
18214
|
-
if (!
|
|
18365
|
+
if (!existsSync8(path2)) return null;
|
|
18215
18366
|
try {
|
|
18216
18367
|
const parsed = JSON.parse(readFileSync6(path2, "utf-8"));
|
|
18217
18368
|
if (!Number.isInteger(parsed.pid) || parsed.pid <= 0) return null;
|
|
@@ -18238,7 +18389,7 @@ var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
18238
18389
|
async function stopProxy(path2 = pidFilePath(), graceMs = 2e3, pollMs = 50) {
|
|
18239
18390
|
const rec = readProxyRecord(path2);
|
|
18240
18391
|
if (!rec) {
|
|
18241
|
-
if (
|
|
18392
|
+
if (existsSync8(path2)) {
|
|
18242
18393
|
removeProxyRecord(path2);
|
|
18243
18394
|
return { kind: "stale", pid: 0, path: path2 };
|
|
18244
18395
|
}
|
|
@@ -18411,17 +18562,17 @@ import chalk3 from "chalk";
|
|
|
18411
18562
|
|
|
18412
18563
|
// src/plan-usage.ts
|
|
18413
18564
|
init_esm_shims();
|
|
18414
|
-
import { existsSync as
|
|
18415
|
-
import { join as
|
|
18565
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
18566
|
+
import { join as join8 } from "path";
|
|
18416
18567
|
import { homedir as homedir4 } from "os";
|
|
18417
18568
|
function credentialsPath() {
|
|
18418
|
-
return
|
|
18569
|
+
return join8(homedir4(), ".pretense", "credentials.json");
|
|
18419
18570
|
}
|
|
18420
18571
|
function readApiKey() {
|
|
18421
18572
|
const fromEnv = process.env["PRETENSE_API_KEY"]?.trim();
|
|
18422
18573
|
if (fromEnv) return fromEnv;
|
|
18423
18574
|
const path2 = credentialsPath();
|
|
18424
|
-
if (!
|
|
18575
|
+
if (!existsSync9(path2)) return null;
|
|
18425
18576
|
try {
|
|
18426
18577
|
const creds = JSON.parse(readFileSync7(path2, "utf-8"));
|
|
18427
18578
|
const key = creds["apiKey"] ?? creds["api_key"];
|
|
@@ -18843,7 +18994,7 @@ import { Command as Command5, Option, InvalidArgumentError as InvalidArgumentErr
|
|
|
18843
18994
|
import chalk5 from "chalk";
|
|
18844
18995
|
import { readFileSync as readFileSync8, statSync as statSync3, readdirSync as readdirSync2, openSync, readSync, closeSync } from "fs";
|
|
18845
18996
|
import { execSync as execSync3 } from "child_process";
|
|
18846
|
-
import { resolve as resolve3, join as
|
|
18997
|
+
import { resolve as resolve3, join as join9, extname as extname2, basename } from "path";
|
|
18847
18998
|
|
|
18848
18999
|
// src/safe-output.ts
|
|
18849
19000
|
init_esm_shims();
|
|
@@ -19033,9 +19184,9 @@ function walkDir(dir) {
|
|
|
19033
19184
|
for (const entry of entries) {
|
|
19034
19185
|
if (entry.isDirectory()) {
|
|
19035
19186
|
if (entry.name.startsWith(".") || SKIP_DIRS.has(entry.name)) continue;
|
|
19036
|
-
files.push(...walkDir(
|
|
19187
|
+
files.push(...walkDir(join9(dir, entry.name)));
|
|
19037
19188
|
} else if (entry.isFile()) {
|
|
19038
|
-
files.push(
|
|
19189
|
+
files.push(join9(dir, entry.name));
|
|
19039
19190
|
}
|
|
19040
19191
|
}
|
|
19041
19192
|
return files;
|
|
@@ -19759,13 +19910,13 @@ function scanCommand() {
|
|
|
19759
19910
|
init_esm_shims();
|
|
19760
19911
|
import { Command as Command6 } from "commander";
|
|
19761
19912
|
import chalk6 from "chalk";
|
|
19762
|
-
import { existsSync as
|
|
19763
|
-
import { join as
|
|
19913
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
|
|
19914
|
+
import { join as join10 } from "path";
|
|
19764
19915
|
function statusCommand() {
|
|
19765
19916
|
return new Command6("status").description("Show Pretense protection status").action(async () => {
|
|
19766
19917
|
const dir = process.cwd();
|
|
19767
|
-
const fingerprintPath =
|
|
19768
|
-
const configPath =
|
|
19918
|
+
const fingerprintPath = join10(dir, ".pretense", "fingerprint.json");
|
|
19919
|
+
const configPath = join10(dir, "pretense.yaml");
|
|
19769
19920
|
console.log(chalk6.cyan("\n Pretense Status\n"));
|
|
19770
19921
|
const record = readProxyRecord(pidFilePath());
|
|
19771
19922
|
if (record && !isProcessAlive(record.pid)) {
|
|
@@ -19787,12 +19938,12 @@ function statusCommand() {
|
|
|
19787
19938
|
console.log(chalk6.yellow(` \u25CB Proxy not running ${chalk6.dim("(run: pretense start)")}`));
|
|
19788
19939
|
}
|
|
19789
19940
|
}
|
|
19790
|
-
if (
|
|
19941
|
+
if (existsSync10(configPath)) {
|
|
19791
19942
|
console.log(chalk6.green(` \u2713 Config: pretense.yaml`));
|
|
19792
19943
|
} else {
|
|
19793
19944
|
console.log(chalk6.yellow(` \u25CB No config ${chalk6.dim("(run: pretense config)")}`));
|
|
19794
19945
|
}
|
|
19795
|
-
if (
|
|
19946
|
+
if (existsSync10(fingerprintPath)) {
|
|
19796
19947
|
try {
|
|
19797
19948
|
const fp = JSON.parse(readFileSync9(fingerprintPath, "utf-8"));
|
|
19798
19949
|
const age = Math.round((Date.now() - fp.scannedAt) / (60 * 1e3));
|
|
@@ -19814,8 +19965,8 @@ function statusCommand() {
|
|
|
19814
19965
|
init_esm_shims();
|
|
19815
19966
|
import { Command as Command7 } from "commander";
|
|
19816
19967
|
import chalk7 from "chalk";
|
|
19817
|
-
import { writeFileSync as writeFileSync4, readFileSync as readFileSync10, existsSync as
|
|
19818
|
-
import { join as
|
|
19968
|
+
import { writeFileSync as writeFileSync4, readFileSync as readFileSync10, existsSync as existsSync11 } from "fs";
|
|
19969
|
+
import { join as join11 } from "path";
|
|
19819
19970
|
import YAML2 from "yaml";
|
|
19820
19971
|
var DEFAULT_CONFIG = {
|
|
19821
19972
|
version: 1,
|
|
@@ -19828,8 +19979,8 @@ function findConfigPath() {
|
|
|
19828
19979
|
const cwd = process.cwd();
|
|
19829
19980
|
const candidates = [".pretense.yaml", "pretense.yaml"];
|
|
19830
19981
|
for (const name of candidates) {
|
|
19831
|
-
const full =
|
|
19832
|
-
if (
|
|
19982
|
+
const full = join11(cwd, name);
|
|
19983
|
+
if (existsSync11(full)) return full;
|
|
19833
19984
|
}
|
|
19834
19985
|
return null;
|
|
19835
19986
|
}
|
|
@@ -19844,7 +19995,7 @@ function loadConfig2() {
|
|
|
19844
19995
|
}
|
|
19845
19996
|
}
|
|
19846
19997
|
function configFilePath() {
|
|
19847
|
-
return findConfigPath() ??
|
|
19998
|
+
return findConfigPath() ?? join11(process.cwd(), "pretense.yaml");
|
|
19848
19999
|
}
|
|
19849
20000
|
function getNestedValue(obj, key) {
|
|
19850
20001
|
const parts = key.split(".");
|
|
@@ -19915,7 +20066,7 @@ function configCommand() {
|
|
|
19915
20066
|
});
|
|
19916
20067
|
cmd.option("--force", "Overwrite existing config with defaults", false).action((opts) => {
|
|
19917
20068
|
if (opts.force) {
|
|
19918
|
-
const outPath =
|
|
20069
|
+
const outPath = join11(process.cwd(), "pretense.yaml");
|
|
19919
20070
|
writeFileSync4(outPath, YAML2.stringify(DEFAULT_CONFIG));
|
|
19920
20071
|
console.log(chalk7.green(`
|
|
19921
20072
|
\u2713 Created pretense.yaml
|
|
@@ -19932,14 +20083,14 @@ init_esm_shims();
|
|
|
19932
20083
|
import { Command as Command8 } from "commander";
|
|
19933
20084
|
import chalk8 from "chalk";
|
|
19934
20085
|
import { homedir as homedir5 } from "os";
|
|
19935
|
-
import { join as
|
|
20086
|
+
import { join as join12 } from "path";
|
|
19936
20087
|
function logsCommand() {
|
|
19937
20088
|
return new Command8("logs").description("Show recent audit log entries").option("-l, --limit <n>", "Number of entries to show", "50").option("--json", "Output as JSON", false).action((opts) => {
|
|
19938
20089
|
const limit = parseInt(opts.limit, 10);
|
|
19939
20090
|
let store;
|
|
19940
20091
|
let entries;
|
|
19941
20092
|
try {
|
|
19942
|
-
store = new AuditStore(
|
|
20093
|
+
store = new AuditStore(join12(homedir5(), ".pretense", "audit.db"));
|
|
19943
20094
|
entries = store.getRecentEntries(limit);
|
|
19944
20095
|
store.close();
|
|
19945
20096
|
} catch {
|
|
@@ -19979,7 +20130,7 @@ function logsCommand() {
|
|
|
19979
20130
|
init_esm_shims();
|
|
19980
20131
|
import { Command as Command9 } from "commander";
|
|
19981
20132
|
import chalk9 from "chalk";
|
|
19982
|
-
import { join as
|
|
20133
|
+
import { join as join13 } from "path";
|
|
19983
20134
|
import { homedir as homedir6 } from "os";
|
|
19984
20135
|
function renderBar(percent, width = 30) {
|
|
19985
20136
|
const filled = Math.min(Math.round(percent / 100 * width), width);
|
|
@@ -20019,7 +20170,7 @@ function emptyUsagePayload(resolution) {
|
|
|
20019
20170
|
};
|
|
20020
20171
|
}
|
|
20021
20172
|
function usageCommand() {
|
|
20022
|
-
return new Command9("usage").description("Show plan usage vs limits for the current billing period").option("--db <path>", "Path to audit database",
|
|
20173
|
+
return new Command9("usage").description("Show plan usage vs limits for the current billing period").option("--db <path>", "Path to audit database", join13(homedir6(), ".pretense", "audit.db")).option("--json", "Output as JSON", false).option("--offline", "Do not contact the plan service to resolve the tier", false).action(async (opts) => {
|
|
20023
20174
|
const resolution = await resolvePlanTier({ offline: opts.offline });
|
|
20024
20175
|
const tier = resolution.tier;
|
|
20025
20176
|
const collected = collectUsage(opts.db);
|
|
@@ -20170,12 +20321,12 @@ function usageCommand() {
|
|
|
20170
20321
|
init_esm_shims();
|
|
20171
20322
|
import { Command as Command10 } from "commander";
|
|
20172
20323
|
import chalk10 from "chalk";
|
|
20173
|
-
import { existsSync as
|
|
20174
|
-
import { join as
|
|
20324
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, unlinkSync as unlinkSync2 } from "fs";
|
|
20325
|
+
import { join as join14 } from "path";
|
|
20175
20326
|
import { homedir as homedir7 } from "os";
|
|
20176
20327
|
import { execSync as execSync4 } from "child_process";
|
|
20177
|
-
var CREDENTIALS_DIR =
|
|
20178
|
-
var CREDENTIALS_PATH =
|
|
20328
|
+
var CREDENTIALS_DIR = join14(homedir7(), ".pretense");
|
|
20329
|
+
var CREDENTIALS_PATH = join14(CREDENTIALS_DIR, "credentials.json");
|
|
20179
20330
|
async function verifyApiKey(apiKey) {
|
|
20180
20331
|
const url = `${getConfiguredApiRoot()}/api/cli/auth/validate`;
|
|
20181
20332
|
const timeoutMs = tierRequestTimeoutMs();
|
|
@@ -20222,7 +20373,7 @@ function storageNotice() {
|
|
|
20222
20373
|
`);
|
|
20223
20374
|
}
|
|
20224
20375
|
function readCredentials() {
|
|
20225
|
-
if (!
|
|
20376
|
+
if (!existsSync12(CREDENTIALS_PATH)) return null;
|
|
20226
20377
|
try {
|
|
20227
20378
|
return JSON.parse(readFileSync11(CREDENTIALS_PATH, "utf-8"));
|
|
20228
20379
|
} catch {
|
|
@@ -20356,7 +20507,7 @@ function authCommand() {
|
|
|
20356
20507
|
openUrl(authUrl);
|
|
20357
20508
|
});
|
|
20358
20509
|
auth.command("logout").description("Remove stored credentials").action(() => {
|
|
20359
|
-
if (!
|
|
20510
|
+
if (!existsSync12(CREDENTIALS_PATH)) {
|
|
20360
20511
|
console.log(chalk10.yellow("\n No credentials found. Already logged out.\n"));
|
|
20361
20512
|
return;
|
|
20362
20513
|
}
|
|
@@ -20411,7 +20562,7 @@ init_esm_shims();
|
|
|
20411
20562
|
import { Command as Command11 } from "commander";
|
|
20412
20563
|
import chalk11 from "chalk";
|
|
20413
20564
|
import { readdirSync as readdirSync3, readFileSync as readFileSync12, statSync as statSync4 } from "fs";
|
|
20414
|
-
import { join as
|
|
20565
|
+
import { join as join15, extname as extname3, relative, isAbsolute } from "path";
|
|
20415
20566
|
var SUPPORTED_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
20416
20567
|
".ts",
|
|
20417
20568
|
".tsx",
|
|
@@ -20446,7 +20597,7 @@ function discoverFiles(dir) {
|
|
|
20446
20597
|
}
|
|
20447
20598
|
for (const entry of entries) {
|
|
20448
20599
|
if (entry.startsWith(".")) continue;
|
|
20449
|
-
const full =
|
|
20600
|
+
const full = join15(current, entry);
|
|
20450
20601
|
let stat;
|
|
20451
20602
|
try {
|
|
20452
20603
|
stat = statSync4(full);
|
|
@@ -20537,7 +20688,7 @@ function formatAgent(results, basePath) {
|
|
|
20537
20688
|
const agentResults = [];
|
|
20538
20689
|
for (const r of results) {
|
|
20539
20690
|
if (r.mutations.length === 0 && r.secrets.length === 0) continue;
|
|
20540
|
-
const filePath =
|
|
20691
|
+
const filePath = join15(basePath, r.file);
|
|
20541
20692
|
let lines;
|
|
20542
20693
|
try {
|
|
20543
20694
|
lines = readFileSync12(filePath, "utf-8").split("\n");
|
|
@@ -20608,7 +20759,7 @@ function formatInteractive(results) {
|
|
|
20608
20759
|
}
|
|
20609
20760
|
function reviewCommand() {
|
|
20610
20761
|
return new Command11("review").description("Preview mutations and secrets that would be applied").argument("[path]", "Directory to review (defaults to current directory)").option("--plain", "Plain text output", false).option("--json", "JSON array output with metadata", false).option("--agent", "Structured JSON optimized for AI agent consumption", false).option("--prompt-only", "Minimal output suitable for piping", false).option("--interactive", "Interactive formatted output (default)", false).action(async (path2, opts) => {
|
|
20611
|
-
const targetDir = path2 ? isAbsolute(path2) ? path2 :
|
|
20762
|
+
const targetDir = path2 ? isAbsolute(path2) ? path2 : join15(process.cwd(), path2) : process.cwd();
|
|
20612
20763
|
const files = discoverFiles(targetDir);
|
|
20613
20764
|
if (files.length === 0) {
|
|
20614
20765
|
if (opts?.json || opts?.agent) {
|
|
@@ -20644,13 +20795,13 @@ init_esm_shims();
|
|
|
20644
20795
|
import { Command as Command12 } from "commander";
|
|
20645
20796
|
import chalk12 from "chalk";
|
|
20646
20797
|
import {
|
|
20647
|
-
existsSync as
|
|
20798
|
+
existsSync as existsSync13,
|
|
20648
20799
|
writeFileSync as writeFileSync5,
|
|
20649
20800
|
chmodSync as chmodSync3,
|
|
20650
20801
|
readFileSync as readFileSync13,
|
|
20651
20802
|
mkdirSync as mkdirSync3
|
|
20652
20803
|
} from "fs";
|
|
20653
|
-
import { join as
|
|
20804
|
+
import { join as join16, resolve as resolve4 } from "path";
|
|
20654
20805
|
var HOOK_SCRIPTS = {
|
|
20655
20806
|
"pre-commit": `#!/bin/sh
|
|
20656
20807
|
# Pretense AI Firewall \u2014 pre-commit hook
|
|
@@ -20669,14 +20820,14 @@ exit $?
|
|
|
20669
20820
|
};
|
|
20670
20821
|
var VALID_MODES = ["pre-commit", "pre-push"];
|
|
20671
20822
|
function findGitDir(cwd) {
|
|
20672
|
-
const gitDir =
|
|
20673
|
-
if (
|
|
20823
|
+
const gitDir = join16(cwd, ".git");
|
|
20824
|
+
if (existsSync13(gitDir)) return gitDir;
|
|
20674
20825
|
return null;
|
|
20675
20826
|
}
|
|
20676
20827
|
function installHook(hooksDir, mode, force) {
|
|
20677
|
-
const hookPath =
|
|
20828
|
+
const hookPath = join16(hooksDir, mode);
|
|
20678
20829
|
const script = HOOK_SCRIPTS[mode];
|
|
20679
|
-
if (
|
|
20830
|
+
if (existsSync13(hookPath) && !force) {
|
|
20680
20831
|
const existing = readFileSync13(hookPath, "utf-8");
|
|
20681
20832
|
if (existing.includes("Pretense AI Firewall")) {
|
|
20682
20833
|
return { installed: false, path: hookPath, skipped: true };
|
|
@@ -20718,7 +20869,7 @@ function installCommand() {
|
|
|
20718
20869
|
);
|
|
20719
20870
|
process.exit(1);
|
|
20720
20871
|
}
|
|
20721
|
-
const hooksDir =
|
|
20872
|
+
const hooksDir = join16(gitDir, "hooks");
|
|
20722
20873
|
mkdirSync3(hooksDir, { recursive: true });
|
|
20723
20874
|
console.log(chalk12.cyan("\n Pretense hook installer\n"));
|
|
20724
20875
|
let hasError = false;
|
|
@@ -20755,22 +20906,22 @@ function installCommand() {
|
|
|
20755
20906
|
init_esm_shims();
|
|
20756
20907
|
import { Command as Command13 } from "commander";
|
|
20757
20908
|
import chalk13 from "chalk";
|
|
20758
|
-
import { appendFileSync as appendFileSync3, readFileSync as readFileSync14, existsSync as
|
|
20759
|
-
import { join as
|
|
20909
|
+
import { appendFileSync as appendFileSync3, readFileSync as readFileSync14, existsSync as existsSync14 } from "fs";
|
|
20910
|
+
import { join as join17 } from "path";
|
|
20760
20911
|
import { homedir as homedir8 } from "os";
|
|
20761
20912
|
var IGNORE_FILE = ".pretenseignore";
|
|
20762
|
-
var LAST_SCAN_PATH =
|
|
20913
|
+
var LAST_SCAN_PATH = join17(homedir8(), ".pretense", "last-scan.json");
|
|
20763
20914
|
function ignorePath() {
|
|
20764
|
-
return
|
|
20915
|
+
return join17(process.cwd(), IGNORE_FILE);
|
|
20765
20916
|
}
|
|
20766
20917
|
function readIgnoreFile() {
|
|
20767
20918
|
const p = ignorePath();
|
|
20768
|
-
if (!
|
|
20919
|
+
if (!existsSync14(p)) return [];
|
|
20769
20920
|
return readFileSync14(p, "utf-8").split("\n").filter((l) => l.length > 0);
|
|
20770
20921
|
}
|
|
20771
20922
|
function appendPattern(pattern) {
|
|
20772
20923
|
const p = ignorePath();
|
|
20773
|
-
const content =
|
|
20924
|
+
const content = existsSync14(p) ? readFileSync14(p, "utf-8") : "";
|
|
20774
20925
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
20775
20926
|
if (lines.includes(pattern)) {
|
|
20776
20927
|
console.log(chalk13.yellow(`
|
|
@@ -20809,7 +20960,7 @@ function ignoreCommand() {
|
|
|
20809
20960
|
return;
|
|
20810
20961
|
}
|
|
20811
20962
|
if (opts.lastFound) {
|
|
20812
|
-
if (!
|
|
20963
|
+
if (!existsSync14(LAST_SCAN_PATH)) {
|
|
20813
20964
|
console.error(chalk13.red(`
|
|
20814
20965
|
\u2717 No last scan results found at ${LAST_SCAN_PATH}
|
|
20815
20966
|
`));
|
|
@@ -21067,8 +21218,8 @@ function completionCommand() {
|
|
|
21067
21218
|
init_esm_shims();
|
|
21068
21219
|
import { Command as Command15 } from "commander";
|
|
21069
21220
|
import chalk14 from "chalk";
|
|
21070
|
-
import { existsSync as
|
|
21071
|
-
import { join as
|
|
21221
|
+
import { existsSync as existsSync15, writeFileSync as writeFileSync6 } from "fs";
|
|
21222
|
+
import { join as join18, resolve as resolve5 } from "path";
|
|
21072
21223
|
var DEFAULT_CONFIG_YAML = `scan:
|
|
21073
21224
|
secrets: block
|
|
21074
21225
|
pii: redact
|
|
@@ -21108,9 +21259,9 @@ function quickstartCommand() {
|
|
|
21108
21259
|
process.exit(1);
|
|
21109
21260
|
}
|
|
21110
21261
|
console.log(chalk14.dim(" [2/4] Writing config..."));
|
|
21111
|
-
const configPath =
|
|
21262
|
+
const configPath = join18(dir, "pretense.yaml");
|
|
21112
21263
|
if (!opts.dryRun) {
|
|
21113
|
-
if (!
|
|
21264
|
+
if (!existsSync15(configPath)) {
|
|
21114
21265
|
writeFileSync6(configPath, DEFAULT_CONFIG_YAML);
|
|
21115
21266
|
console.log(chalk14.green(" Created pretense.yaml"));
|
|
21116
21267
|
} else {
|
|
@@ -21119,8 +21270,8 @@ function quickstartCommand() {
|
|
|
21119
21270
|
}
|
|
21120
21271
|
console.log(chalk14.dim(" [3/4] Updating .gitignore..."));
|
|
21121
21272
|
if (!opts.dryRun) {
|
|
21122
|
-
const gitignorePath =
|
|
21123
|
-
let content =
|
|
21273
|
+
const gitignorePath = join18(dir, ".gitignore");
|
|
21274
|
+
let content = existsSync15(gitignorePath) ? (await import("fs")).default.readFileSync(gitignorePath, "utf-8") : "";
|
|
21124
21275
|
if (!content.includes(".pretense/")) {
|
|
21125
21276
|
content = content + (content.endsWith("\n") ? "" : "\n") + ".pretense/\n";
|
|
21126
21277
|
writeFileSync6(gitignorePath, content);
|
|
@@ -21150,7 +21301,7 @@ function quickstartCommand() {
|
|
|
21150
21301
|
init_esm_shims();
|
|
21151
21302
|
import { Command as Command16, Option as Option2 } from "commander";
|
|
21152
21303
|
import chalk16 from "chalk";
|
|
21153
|
-
import { readFileSync as readFileSync15, writeFileSync as writeFileSync7, chmodSync as chmodSync4, existsSync as
|
|
21304
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync7, chmodSync as chmodSync4, existsSync as existsSync16 } from "fs";
|
|
21154
21305
|
import { createHash as createHash3 } from "crypto";
|
|
21155
21306
|
import { resolve as resolve6, extname as extname4 } from "path";
|
|
21156
21307
|
|
|
@@ -21158,8 +21309,8 @@ import { resolve as resolve6, extname as extname4 } from "path";
|
|
|
21158
21309
|
init_esm_shims();
|
|
21159
21310
|
import { createCipheriv, createDecipheriv, randomBytes as randomBytes3, hkdfSync as hkdfSync2 } from "crypto";
|
|
21160
21311
|
import { homedir as homedir9 } from "os";
|
|
21161
|
-
import { join as
|
|
21162
|
-
var KEYS_DIR =
|
|
21312
|
+
import { join as join19 } from "path";
|
|
21313
|
+
var KEYS_DIR = join19(homedir9(), ".pretense", "keys");
|
|
21163
21314
|
var HKDF_SALT2 = Buffer.from("pretense-maps-v1", "utf-8");
|
|
21164
21315
|
var HKDF_INFO2 = Buffer.from("secret-mapping-aes-256-gcm", "utf-8");
|
|
21165
21316
|
var IV_LEN = 12;
|
|
@@ -21204,13 +21355,13 @@ import {
|
|
|
21204
21355
|
fchmodSync
|
|
21205
21356
|
} from "fs";
|
|
21206
21357
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
21207
|
-
import { dirname as dirname4, basename as basename2, join as
|
|
21358
|
+
import { dirname as dirname4, basename as basename2, join as join20 } from "path";
|
|
21208
21359
|
function writeFileAtomicSync(targetPath, data, opts = {}) {
|
|
21209
21360
|
let resolved;
|
|
21210
21361
|
try {
|
|
21211
21362
|
resolved = realpathSync2(targetPath);
|
|
21212
21363
|
} catch {
|
|
21213
|
-
resolved =
|
|
21364
|
+
resolved = join20(realpathSync2(dirname4(targetPath)), basename2(targetPath));
|
|
21214
21365
|
}
|
|
21215
21366
|
let mode = opts.mode;
|
|
21216
21367
|
if (mode === void 0) {
|
|
@@ -21221,7 +21372,7 @@ function writeFileAtomicSync(targetPath, data, opts = {}) {
|
|
|
21221
21372
|
}
|
|
21222
21373
|
}
|
|
21223
21374
|
const dir = dirname4(resolved);
|
|
21224
|
-
const tmp =
|
|
21375
|
+
const tmp = join20(dir, `.${basename2(resolved)}.pretense-${randomBytes4(6).toString("hex")}.tmp`);
|
|
21225
21376
|
const buf = Buffer.isBuffer(data) ? data : Buffer.from(data, "utf-8");
|
|
21226
21377
|
let fd = openSync2(tmp, "wx", 384);
|
|
21227
21378
|
try {
|
|
@@ -21262,13 +21413,13 @@ function writeFileAtomicSync(targetPath, data, opts = {}) {
|
|
|
21262
21413
|
// src/default-map.ts
|
|
21263
21414
|
init_esm_shims();
|
|
21264
21415
|
import { createHash as createHash2 } from "crypto";
|
|
21265
|
-
import { join as
|
|
21416
|
+
import { join as join21 } from "path";
|
|
21266
21417
|
function mapsDir(override2) {
|
|
21267
|
-
return override2 ??
|
|
21418
|
+
return override2 ?? join21(pretenseHome(), "maps");
|
|
21268
21419
|
}
|
|
21269
21420
|
function defaultMapPath(absFilePath, override2) {
|
|
21270
21421
|
const digest = createHash2("sha256").update(absFilePath, "utf8").digest("hex");
|
|
21271
|
-
return
|
|
21422
|
+
return join21(mapsDir(override2), `${digest}.json`);
|
|
21272
21423
|
}
|
|
21273
21424
|
function ensureDefaultMapPath(absFilePath, override2) {
|
|
21274
21425
|
ensureDirOwnerOnly(mapsDir(override2));
|
|
@@ -21278,11 +21429,11 @@ function ensureDefaultMapPath(absFilePath, override2) {
|
|
|
21278
21429
|
// src/local-audit.ts
|
|
21279
21430
|
init_esm_shims();
|
|
21280
21431
|
import { homedir as homedir10 } from "os";
|
|
21281
|
-
import { join as
|
|
21432
|
+
import { join as join24 } from "path";
|
|
21282
21433
|
import { randomUUID } from "crypto";
|
|
21283
21434
|
import chalk15 from "chalk";
|
|
21284
21435
|
function localAuditDbPath() {
|
|
21285
|
-
return
|
|
21436
|
+
return join24(homedir10(), ".pretense", "audit.db");
|
|
21286
21437
|
}
|
|
21287
21438
|
function recordLocalAudit(rec, dbPath = localAuditDbPath()) {
|
|
21288
21439
|
let store = null;
|
|
@@ -21317,10 +21468,71 @@ function recordLocalAudit(rec, dbPath = localAuditDbPath()) {
|
|
|
21317
21468
|
}
|
|
21318
21469
|
}
|
|
21319
21470
|
|
|
21471
|
+
// src/usage-upload.ts
|
|
21472
|
+
init_esm_shims();
|
|
21473
|
+
var UPLOAD_TIMEOUT_MS2 = 3e3;
|
|
21474
|
+
function telemetryDisabled2() {
|
|
21475
|
+
const v = process.env["PRETENSE_NO_TELEMETRY"]?.trim().toLowerCase();
|
|
21476
|
+
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
21477
|
+
}
|
|
21478
|
+
function resolveUploadBaseUrl2() {
|
|
21479
|
+
const raw2 = process.env["PRETENSE_DASHBOARD_URL"]?.trim();
|
|
21480
|
+
if (!raw2) return getConfiguredApiRoot();
|
|
21481
|
+
const normalized = /^https?:\/\//i.test(raw2) ? raw2 : `https://${raw2}`;
|
|
21482
|
+
try {
|
|
21483
|
+
const u = new URL(normalized);
|
|
21484
|
+
const path2 = u.pathname === "/" ? "" : u.pathname.replace(/\/$/, "");
|
|
21485
|
+
return `${u.origin}${path2}`;
|
|
21486
|
+
} catch {
|
|
21487
|
+
return getConfiguredApiRoot();
|
|
21488
|
+
}
|
|
21489
|
+
}
|
|
21490
|
+
function resolveUploadKey2() {
|
|
21491
|
+
const dashboardKey = process.env["PRETENSE_DASHBOARD_API_KEY"]?.trim();
|
|
21492
|
+
if (dashboardKey) return dashboardKey;
|
|
21493
|
+
return readApiKey();
|
|
21494
|
+
}
|
|
21495
|
+
function clampCount2(n) {
|
|
21496
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
|
|
21497
|
+
}
|
|
21498
|
+
async function uploadUsage(event) {
|
|
21499
|
+
try {
|
|
21500
|
+
if (telemetryDisabled2()) return "skipped";
|
|
21501
|
+
const key = resolveUploadKey2();
|
|
21502
|
+
if (!key) return "skipped";
|
|
21503
|
+
const url = `${resolveUploadBaseUrl2()}/api/cli/log`;
|
|
21504
|
+
const controller = new AbortController();
|
|
21505
|
+
const timer = setTimeout(() => controller.abort(), UPLOAD_TIMEOUT_MS2);
|
|
21506
|
+
try {
|
|
21507
|
+
const resp = await fetch(url, {
|
|
21508
|
+
method: "POST",
|
|
21509
|
+
headers: {
|
|
21510
|
+
"content-type": "application/json",
|
|
21511
|
+
authorization: `Bearer ${key}`
|
|
21512
|
+
},
|
|
21513
|
+
// COUNTS + METADATA ONLY — never a secret value, an identifier name, or
|
|
21514
|
+
// file content. Field names match the `/api/cli/log` contract.
|
|
21515
|
+
body: JSON.stringify({
|
|
21516
|
+
file_count: clampCount2(event.fileCount),
|
|
21517
|
+
identifiers_mutated: clampCount2(event.identifiersMutated),
|
|
21518
|
+
secrets_blocked: clampCount2(event.secretsBlocked),
|
|
21519
|
+
llm_provider: event.llmProvider
|
|
21520
|
+
}),
|
|
21521
|
+
signal: controller.signal
|
|
21522
|
+
});
|
|
21523
|
+
return resp.ok ? "sent" : "failed";
|
|
21524
|
+
} finally {
|
|
21525
|
+
clearTimeout(timer);
|
|
21526
|
+
}
|
|
21527
|
+
} catch {
|
|
21528
|
+
return "failed";
|
|
21529
|
+
}
|
|
21530
|
+
}
|
|
21531
|
+
|
|
21320
21532
|
// src/commands/mutate.ts
|
|
21321
21533
|
var REVERSAL_MAP_VERSION = 3;
|
|
21322
21534
|
function preflightReversalMap(mapPath, absFile, content, contentSha, force) {
|
|
21323
|
-
if (!
|
|
21535
|
+
if (!existsSync16(mapPath)) return { action: "write", generation: 1 };
|
|
21324
21536
|
let existing;
|
|
21325
21537
|
try {
|
|
21326
21538
|
const parsed = JSON.parse(readFileSync15(mapPath, "utf-8"));
|
|
@@ -21497,7 +21709,25 @@ async function runMutate(file, opts = {}) {
|
|
|
21497
21709
|
opts.level,
|
|
21498
21710
|
opts.presetName
|
|
21499
21711
|
);
|
|
21500
|
-
|
|
21712
|
+
const absFile = resolve6(file);
|
|
21713
|
+
const projectRoot = resolveProjectRoot(absFile);
|
|
21714
|
+
const secretResult = mutateSecrets(content, findings, { projectRoot, keysDir: opts.keysDir });
|
|
21715
|
+
const fingerprintIds = loadFingerprintIdentifiers(projectRoot);
|
|
21716
|
+
const idMut = fingerprintIds.length > 0 ? mutateNamedIdentifiers(
|
|
21717
|
+
secretResult.content,
|
|
21718
|
+
L2_LANGUAGE_BY_EXT2[extname4(file).toLowerCase()],
|
|
21719
|
+
fingerprintIds,
|
|
21720
|
+
"pretense",
|
|
21721
|
+
{ projectRoot, keysDir: opts.keysDir }
|
|
21722
|
+
) : { mutatedCode: secretResult.content, map: /* @__PURE__ */ new Map() };
|
|
21723
|
+
const finalContent = idMut.mutatedCode;
|
|
21724
|
+
const identifierMutations = [...idMut.map.entries()].map(([original, replacement]) => ({
|
|
21725
|
+
original,
|
|
21726
|
+
replacement,
|
|
21727
|
+
type: "proprietary"
|
|
21728
|
+
}));
|
|
21729
|
+
const totalMutations = secretResult.mutations.length + identifierMutations.length;
|
|
21730
|
+
if (totalMutations === 0) {
|
|
21501
21731
|
if (unmutatable.size === 0) {
|
|
21502
21732
|
console.error(chalk16.dim(` No secrets found in ${file} \u2014 nothing to mutate.`));
|
|
21503
21733
|
} else {
|
|
@@ -21507,9 +21737,10 @@ async function runMutate(file, opts = {}) {
|
|
|
21507
21737
|
return 0;
|
|
21508
21738
|
}
|
|
21509
21739
|
reportUnmutatable(unmutatable);
|
|
21510
|
-
const
|
|
21511
|
-
|
|
21512
|
-
|
|
21740
|
+
const result = {
|
|
21741
|
+
content: finalContent,
|
|
21742
|
+
mutations: [...secretResult.mutations, ...identifierMutations]
|
|
21743
|
+
};
|
|
21513
21744
|
let effectiveMap;
|
|
21514
21745
|
if (preview) {
|
|
21515
21746
|
effectiveMap = void 0;
|
|
@@ -21581,13 +21812,21 @@ async function runMutate(file, opts = {}) {
|
|
|
21581
21812
|
);
|
|
21582
21813
|
return 1;
|
|
21583
21814
|
}
|
|
21815
|
+
const secretCount = secretResult.mutations.length;
|
|
21816
|
+
const idCount = identifierMutations.length;
|
|
21817
|
+
const summary = () => {
|
|
21818
|
+
const parts = [];
|
|
21819
|
+
if (secretCount > 0) parts.push(`${secretCount} secret${secretCount === 1 ? "" : "s"}`);
|
|
21820
|
+
if (idCount > 0) parts.push(`${idCount} registered identifier${idCount === 1 ? "" : "s"}`);
|
|
21821
|
+
return parts.join(" + ");
|
|
21822
|
+
};
|
|
21584
21823
|
try {
|
|
21585
21824
|
if (inPlace) {
|
|
21586
21825
|
writeFileAtomicSync(file, result.content);
|
|
21587
|
-
console.error(chalk16.green(` \u2713 Mutated ${
|
|
21826
|
+
console.error(chalk16.green(` \u2713 Mutated ${summary()} in ${file} (in-place)`));
|
|
21588
21827
|
} else if (opts.output) {
|
|
21589
21828
|
writeFileAtomicSync(opts.output, result.content);
|
|
21590
|
-
console.error(chalk16.green(` \u2713 Mutated ${
|
|
21829
|
+
console.error(chalk16.green(` \u2713 Mutated ${summary()} \u2192 ${opts.output}`));
|
|
21591
21830
|
} else {
|
|
21592
21831
|
process.stdout.write(result.content);
|
|
21593
21832
|
}
|
|
@@ -21604,7 +21843,9 @@ async function runMutate(file, opts = {}) {
|
|
|
21604
21843
|
let secretsBlocked = 0;
|
|
21605
21844
|
let piiRedacted = 0;
|
|
21606
21845
|
for (const m of result.mutations) {
|
|
21607
|
-
|
|
21846
|
+
const cat = categoryByType.get(m.type);
|
|
21847
|
+
if (cat === "pii") piiRedacted += 1;
|
|
21848
|
+
else if (m.type === "proprietary") continue;
|
|
21608
21849
|
else secretsBlocked += 1;
|
|
21609
21850
|
}
|
|
21610
21851
|
recordLocalAudit({
|
|
@@ -21618,6 +21859,12 @@ async function runMutate(file, opts = {}) {
|
|
|
21618
21859
|
detectorKinds: [...new Set(result.mutations.map((m) => m.type))],
|
|
21619
21860
|
file: absFile
|
|
21620
21861
|
});
|
|
21862
|
+
await uploadUsage({
|
|
21863
|
+
fileCount: 1,
|
|
21864
|
+
identifiersMutated: result.mutations.length,
|
|
21865
|
+
secretsBlocked,
|
|
21866
|
+
llmProvider: "cli-mutate"
|
|
21867
|
+
});
|
|
21621
21868
|
}
|
|
21622
21869
|
if (opts.showMap) {
|
|
21623
21870
|
console.error(JSON.stringify(result.mutations, null, 2));
|
|
@@ -21660,7 +21907,7 @@ function mutateCommand() {
|
|
|
21660
21907
|
init_esm_shims();
|
|
21661
21908
|
import { Command as Command17 } from "commander";
|
|
21662
21909
|
import chalk17 from "chalk";
|
|
21663
|
-
import { readFileSync as readFileSync16, existsSync as
|
|
21910
|
+
import { readFileSync as readFileSync16, existsSync as existsSync17, statSync as statSync6 } from "fs";
|
|
21664
21911
|
import { resolve as resolve7 } from "path";
|
|
21665
21912
|
import { createHash as createHash4 } from "crypto";
|
|
21666
21913
|
function sha256Hex3(s) {
|
|
@@ -21721,14 +21968,14 @@ function loadReversalMap(mapPath) {
|
|
|
21721
21968
|
function runReverse(file, opts = {}) {
|
|
21722
21969
|
const reverseStartMs = Date.now();
|
|
21723
21970
|
const absPath = resolve7(file);
|
|
21724
|
-
if (!
|
|
21971
|
+
if (!existsSync17(absPath) || !statSync6(absPath).isFile()) {
|
|
21725
21972
|
console.error(chalk17.red(`
|
|
21726
21973
|
x File not found: ${file}
|
|
21727
21974
|
`));
|
|
21728
21975
|
return 1;
|
|
21729
21976
|
}
|
|
21730
21977
|
const mapPath = opts.map ?? defaultMapPath(absPath, opts.mapsDir);
|
|
21731
|
-
if (!opts.map && !
|
|
21978
|
+
if (!opts.map && !existsSync17(mapPath)) {
|
|
21732
21979
|
console.error(
|
|
21733
21980
|
chalk17.red(`
|
|
21734
21981
|
x No reversal map found for ${absPath}`) + chalk17.dim(`
|
|
@@ -22185,7 +22432,7 @@ init_esm_shims();
|
|
|
22185
22432
|
import { Command as Command20 } from "commander";
|
|
22186
22433
|
import chalk20 from "chalk";
|
|
22187
22434
|
import { homedir as homedir11 } from "os";
|
|
22188
|
-
import { join as
|
|
22435
|
+
import { join as join25 } from "path";
|
|
22189
22436
|
var VALID_FORMATS2 = ["table", "csv", "json", "jsonl"];
|
|
22190
22437
|
function toSafeAuditRow(e) {
|
|
22191
22438
|
return {
|
|
@@ -22309,7 +22556,7 @@ function auditCommand() {
|
|
|
22309
22556
|
`));
|
|
22310
22557
|
process.exit(1);
|
|
22311
22558
|
}
|
|
22312
|
-
const dbPath = opts.db ??
|
|
22559
|
+
const dbPath = opts.db ?? join25(homedir11(), ".pretense", "audit.db");
|
|
22313
22560
|
let rows;
|
|
22314
22561
|
try {
|
|
22315
22562
|
const store = new AuditStore(dbPath);
|
|
@@ -22369,7 +22616,7 @@ function auditCommand() {
|
|
|
22369
22616
|
init_esm_shims();
|
|
22370
22617
|
import { Command as Command21 } from "commander";
|
|
22371
22618
|
import chalk21 from "chalk";
|
|
22372
|
-
import { join as
|
|
22619
|
+
import { join as join26 } from "path";
|
|
22373
22620
|
import { homedir as homedir12 } from "os";
|
|
22374
22621
|
function remaining(used, limit) {
|
|
22375
22622
|
if (limit === null) return null;
|
|
@@ -22388,7 +22635,7 @@ function bar(used, limit, width = 24) {
|
|
|
22388
22635
|
return chalk21.green(s);
|
|
22389
22636
|
}
|
|
22390
22637
|
function creditsCommand() {
|
|
22391
|
-
return new Command21("credits").alias("tokens").description("Show remaining mutation budget for the current period").option("--db <path>", "Path to audit database",
|
|
22638
|
+
return new Command21("credits").alias("tokens").description("Show remaining mutation budget for the current period").option("--db <path>", "Path to audit database", join26(homedir12(), ".pretense", "audit.db")).option("--json", "Output as JSON", false).option("--offline", "Do not contact the plan service to resolve the tier", false).action(async (opts) => {
|
|
22392
22639
|
const resolution = await resolvePlanTier({ offline: opts.offline });
|
|
22393
22640
|
const tier = resolution.tier;
|
|
22394
22641
|
const collected = collectUsage(opts.db);
|
package/dist/postinstall.js
CHANGED