@pretense/cli 0.6.20 → 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-N2GZIZAD.js → chunk-2BMR5XBU.js} +1 -1
- package/dist/index.js +213 -101
- package/dist/postinstall.js +1 -1
- package/package.json +4 -4
|
@@ -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",
|
|
@@ -17591,6 +17666,7 @@ function createProxy(opts = {}) {
|
|
|
17591
17666
|
}
|
|
17592
17667
|
const app = new Hono2();
|
|
17593
17668
|
const derivation = { projectRoot: resolveProxyProjectRoot(opts.projectRoot) };
|
|
17669
|
+
const fingerprintIdentifiers = loadFingerprintIdentifiers(derivation.projectRoot);
|
|
17594
17670
|
let auditWriteFailures = 0;
|
|
17595
17671
|
let auditWriteFailureLogged = false;
|
|
17596
17672
|
const safeLog = (entry) => {
|
|
@@ -17958,9 +18034,16 @@ ${_upgradeTier === "enterprise" ? "Enterprise offers unlimited mutations \u2014
|
|
|
17958
18034
|
continue;
|
|
17959
18035
|
}
|
|
17960
18036
|
const result = mutate(block.code, block.language, "pretense", derivation);
|
|
18037
|
+
let blockCode = result.mutatedCode;
|
|
17961
18038
|
for (const [k, v] of result.map.entries()) globalMap.set(k, v);
|
|
17962
18039
|
tokensMutated += result.stats.tokensMutated;
|
|
17963
|
-
|
|
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);
|
|
17964
18047
|
}
|
|
17965
18048
|
return replaceCodeBlocks(text, blocks, mutatedBlocks);
|
|
17966
18049
|
});
|
|
@@ -18263,11 +18346,11 @@ async function findFreePort(start, opts = {}) {
|
|
|
18263
18346
|
|
|
18264
18347
|
// src/proxy-pidfile.ts
|
|
18265
18348
|
init_esm_shims();
|
|
18266
|
-
import { existsSync as
|
|
18267
|
-
import { join as
|
|
18349
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, unlinkSync } from "fs";
|
|
18350
|
+
import { join as join7 } from "path";
|
|
18268
18351
|
import { homedir as homedir3 } from "os";
|
|
18269
18352
|
function pidFilePath(home = homedir3()) {
|
|
18270
|
-
return
|
|
18353
|
+
return join7(process.env.PRETENSE_PID_DIR ?? join7(home, ".pretense"), "proxy.pid");
|
|
18271
18354
|
}
|
|
18272
18355
|
function isProcessAlive(pid) {
|
|
18273
18356
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -18279,7 +18362,7 @@ function isProcessAlive(pid) {
|
|
|
18279
18362
|
}
|
|
18280
18363
|
}
|
|
18281
18364
|
function readProxyRecord(path2 = pidFilePath()) {
|
|
18282
|
-
if (!
|
|
18365
|
+
if (!existsSync8(path2)) return null;
|
|
18283
18366
|
try {
|
|
18284
18367
|
const parsed = JSON.parse(readFileSync6(path2, "utf-8"));
|
|
18285
18368
|
if (!Number.isInteger(parsed.pid) || parsed.pid <= 0) return null;
|
|
@@ -18306,7 +18389,7 @@ var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
18306
18389
|
async function stopProxy(path2 = pidFilePath(), graceMs = 2e3, pollMs = 50) {
|
|
18307
18390
|
const rec = readProxyRecord(path2);
|
|
18308
18391
|
if (!rec) {
|
|
18309
|
-
if (
|
|
18392
|
+
if (existsSync8(path2)) {
|
|
18310
18393
|
removeProxyRecord(path2);
|
|
18311
18394
|
return { kind: "stale", pid: 0, path: path2 };
|
|
18312
18395
|
}
|
|
@@ -18479,17 +18562,17 @@ import chalk3 from "chalk";
|
|
|
18479
18562
|
|
|
18480
18563
|
// src/plan-usage.ts
|
|
18481
18564
|
init_esm_shims();
|
|
18482
|
-
import { existsSync as
|
|
18483
|
-
import { join as
|
|
18565
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
18566
|
+
import { join as join8 } from "path";
|
|
18484
18567
|
import { homedir as homedir4 } from "os";
|
|
18485
18568
|
function credentialsPath() {
|
|
18486
|
-
return
|
|
18569
|
+
return join8(homedir4(), ".pretense", "credentials.json");
|
|
18487
18570
|
}
|
|
18488
18571
|
function readApiKey() {
|
|
18489
18572
|
const fromEnv = process.env["PRETENSE_API_KEY"]?.trim();
|
|
18490
18573
|
if (fromEnv) return fromEnv;
|
|
18491
18574
|
const path2 = credentialsPath();
|
|
18492
|
-
if (!
|
|
18575
|
+
if (!existsSync9(path2)) return null;
|
|
18493
18576
|
try {
|
|
18494
18577
|
const creds = JSON.parse(readFileSync7(path2, "utf-8"));
|
|
18495
18578
|
const key = creds["apiKey"] ?? creds["api_key"];
|
|
@@ -18911,7 +18994,7 @@ import { Command as Command5, Option, InvalidArgumentError as InvalidArgumentErr
|
|
|
18911
18994
|
import chalk5 from "chalk";
|
|
18912
18995
|
import { readFileSync as readFileSync8, statSync as statSync3, readdirSync as readdirSync2, openSync, readSync, closeSync } from "fs";
|
|
18913
18996
|
import { execSync as execSync3 } from "child_process";
|
|
18914
|
-
import { resolve as resolve3, join as
|
|
18997
|
+
import { resolve as resolve3, join as join9, extname as extname2, basename } from "path";
|
|
18915
18998
|
|
|
18916
18999
|
// src/safe-output.ts
|
|
18917
19000
|
init_esm_shims();
|
|
@@ -19101,9 +19184,9 @@ function walkDir(dir) {
|
|
|
19101
19184
|
for (const entry of entries) {
|
|
19102
19185
|
if (entry.isDirectory()) {
|
|
19103
19186
|
if (entry.name.startsWith(".") || SKIP_DIRS.has(entry.name)) continue;
|
|
19104
|
-
files.push(...walkDir(
|
|
19187
|
+
files.push(...walkDir(join9(dir, entry.name)));
|
|
19105
19188
|
} else if (entry.isFile()) {
|
|
19106
|
-
files.push(
|
|
19189
|
+
files.push(join9(dir, entry.name));
|
|
19107
19190
|
}
|
|
19108
19191
|
}
|
|
19109
19192
|
return files;
|
|
@@ -19827,13 +19910,13 @@ function scanCommand() {
|
|
|
19827
19910
|
init_esm_shims();
|
|
19828
19911
|
import { Command as Command6 } from "commander";
|
|
19829
19912
|
import chalk6 from "chalk";
|
|
19830
|
-
import { existsSync as
|
|
19831
|
-
import { join as
|
|
19913
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
|
|
19914
|
+
import { join as join10 } from "path";
|
|
19832
19915
|
function statusCommand() {
|
|
19833
19916
|
return new Command6("status").description("Show Pretense protection status").action(async () => {
|
|
19834
19917
|
const dir = process.cwd();
|
|
19835
|
-
const fingerprintPath =
|
|
19836
|
-
const configPath =
|
|
19918
|
+
const fingerprintPath = join10(dir, ".pretense", "fingerprint.json");
|
|
19919
|
+
const configPath = join10(dir, "pretense.yaml");
|
|
19837
19920
|
console.log(chalk6.cyan("\n Pretense Status\n"));
|
|
19838
19921
|
const record = readProxyRecord(pidFilePath());
|
|
19839
19922
|
if (record && !isProcessAlive(record.pid)) {
|
|
@@ -19855,12 +19938,12 @@ function statusCommand() {
|
|
|
19855
19938
|
console.log(chalk6.yellow(` \u25CB Proxy not running ${chalk6.dim("(run: pretense start)")}`));
|
|
19856
19939
|
}
|
|
19857
19940
|
}
|
|
19858
|
-
if (
|
|
19941
|
+
if (existsSync10(configPath)) {
|
|
19859
19942
|
console.log(chalk6.green(` \u2713 Config: pretense.yaml`));
|
|
19860
19943
|
} else {
|
|
19861
19944
|
console.log(chalk6.yellow(` \u25CB No config ${chalk6.dim("(run: pretense config)")}`));
|
|
19862
19945
|
}
|
|
19863
|
-
if (
|
|
19946
|
+
if (existsSync10(fingerprintPath)) {
|
|
19864
19947
|
try {
|
|
19865
19948
|
const fp = JSON.parse(readFileSync9(fingerprintPath, "utf-8"));
|
|
19866
19949
|
const age = Math.round((Date.now() - fp.scannedAt) / (60 * 1e3));
|
|
@@ -19882,8 +19965,8 @@ function statusCommand() {
|
|
|
19882
19965
|
init_esm_shims();
|
|
19883
19966
|
import { Command as Command7 } from "commander";
|
|
19884
19967
|
import chalk7 from "chalk";
|
|
19885
|
-
import { writeFileSync as writeFileSync4, readFileSync as readFileSync10, existsSync as
|
|
19886
|
-
import { join as
|
|
19968
|
+
import { writeFileSync as writeFileSync4, readFileSync as readFileSync10, existsSync as existsSync11 } from "fs";
|
|
19969
|
+
import { join as join11 } from "path";
|
|
19887
19970
|
import YAML2 from "yaml";
|
|
19888
19971
|
var DEFAULT_CONFIG = {
|
|
19889
19972
|
version: 1,
|
|
@@ -19896,8 +19979,8 @@ function findConfigPath() {
|
|
|
19896
19979
|
const cwd = process.cwd();
|
|
19897
19980
|
const candidates = [".pretense.yaml", "pretense.yaml"];
|
|
19898
19981
|
for (const name of candidates) {
|
|
19899
|
-
const full =
|
|
19900
|
-
if (
|
|
19982
|
+
const full = join11(cwd, name);
|
|
19983
|
+
if (existsSync11(full)) return full;
|
|
19901
19984
|
}
|
|
19902
19985
|
return null;
|
|
19903
19986
|
}
|
|
@@ -19912,7 +19995,7 @@ function loadConfig2() {
|
|
|
19912
19995
|
}
|
|
19913
19996
|
}
|
|
19914
19997
|
function configFilePath() {
|
|
19915
|
-
return findConfigPath() ??
|
|
19998
|
+
return findConfigPath() ?? join11(process.cwd(), "pretense.yaml");
|
|
19916
19999
|
}
|
|
19917
20000
|
function getNestedValue(obj, key) {
|
|
19918
20001
|
const parts = key.split(".");
|
|
@@ -19983,7 +20066,7 @@ function configCommand() {
|
|
|
19983
20066
|
});
|
|
19984
20067
|
cmd.option("--force", "Overwrite existing config with defaults", false).action((opts) => {
|
|
19985
20068
|
if (opts.force) {
|
|
19986
|
-
const outPath =
|
|
20069
|
+
const outPath = join11(process.cwd(), "pretense.yaml");
|
|
19987
20070
|
writeFileSync4(outPath, YAML2.stringify(DEFAULT_CONFIG));
|
|
19988
20071
|
console.log(chalk7.green(`
|
|
19989
20072
|
\u2713 Created pretense.yaml
|
|
@@ -20000,14 +20083,14 @@ init_esm_shims();
|
|
|
20000
20083
|
import { Command as Command8 } from "commander";
|
|
20001
20084
|
import chalk8 from "chalk";
|
|
20002
20085
|
import { homedir as homedir5 } from "os";
|
|
20003
|
-
import { join as
|
|
20086
|
+
import { join as join12 } from "path";
|
|
20004
20087
|
function logsCommand() {
|
|
20005
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) => {
|
|
20006
20089
|
const limit = parseInt(opts.limit, 10);
|
|
20007
20090
|
let store;
|
|
20008
20091
|
let entries;
|
|
20009
20092
|
try {
|
|
20010
|
-
store = new AuditStore(
|
|
20093
|
+
store = new AuditStore(join12(homedir5(), ".pretense", "audit.db"));
|
|
20011
20094
|
entries = store.getRecentEntries(limit);
|
|
20012
20095
|
store.close();
|
|
20013
20096
|
} catch {
|
|
@@ -20047,7 +20130,7 @@ function logsCommand() {
|
|
|
20047
20130
|
init_esm_shims();
|
|
20048
20131
|
import { Command as Command9 } from "commander";
|
|
20049
20132
|
import chalk9 from "chalk";
|
|
20050
|
-
import { join as
|
|
20133
|
+
import { join as join13 } from "path";
|
|
20051
20134
|
import { homedir as homedir6 } from "os";
|
|
20052
20135
|
function renderBar(percent, width = 30) {
|
|
20053
20136
|
const filled = Math.min(Math.round(percent / 100 * width), width);
|
|
@@ -20087,7 +20170,7 @@ function emptyUsagePayload(resolution) {
|
|
|
20087
20170
|
};
|
|
20088
20171
|
}
|
|
20089
20172
|
function usageCommand() {
|
|
20090
|
-
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) => {
|
|
20091
20174
|
const resolution = await resolvePlanTier({ offline: opts.offline });
|
|
20092
20175
|
const tier = resolution.tier;
|
|
20093
20176
|
const collected = collectUsage(opts.db);
|
|
@@ -20238,12 +20321,12 @@ function usageCommand() {
|
|
|
20238
20321
|
init_esm_shims();
|
|
20239
20322
|
import { Command as Command10 } from "commander";
|
|
20240
20323
|
import chalk10 from "chalk";
|
|
20241
|
-
import { existsSync as
|
|
20242
|
-
import { join as
|
|
20324
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, unlinkSync as unlinkSync2 } from "fs";
|
|
20325
|
+
import { join as join14 } from "path";
|
|
20243
20326
|
import { homedir as homedir7 } from "os";
|
|
20244
20327
|
import { execSync as execSync4 } from "child_process";
|
|
20245
|
-
var CREDENTIALS_DIR =
|
|
20246
|
-
var CREDENTIALS_PATH =
|
|
20328
|
+
var CREDENTIALS_DIR = join14(homedir7(), ".pretense");
|
|
20329
|
+
var CREDENTIALS_PATH = join14(CREDENTIALS_DIR, "credentials.json");
|
|
20247
20330
|
async function verifyApiKey(apiKey) {
|
|
20248
20331
|
const url = `${getConfiguredApiRoot()}/api/cli/auth/validate`;
|
|
20249
20332
|
const timeoutMs = tierRequestTimeoutMs();
|
|
@@ -20290,7 +20373,7 @@ function storageNotice() {
|
|
|
20290
20373
|
`);
|
|
20291
20374
|
}
|
|
20292
20375
|
function readCredentials() {
|
|
20293
|
-
if (!
|
|
20376
|
+
if (!existsSync12(CREDENTIALS_PATH)) return null;
|
|
20294
20377
|
try {
|
|
20295
20378
|
return JSON.parse(readFileSync11(CREDENTIALS_PATH, "utf-8"));
|
|
20296
20379
|
} catch {
|
|
@@ -20424,7 +20507,7 @@ function authCommand() {
|
|
|
20424
20507
|
openUrl(authUrl);
|
|
20425
20508
|
});
|
|
20426
20509
|
auth.command("logout").description("Remove stored credentials").action(() => {
|
|
20427
|
-
if (!
|
|
20510
|
+
if (!existsSync12(CREDENTIALS_PATH)) {
|
|
20428
20511
|
console.log(chalk10.yellow("\n No credentials found. Already logged out.\n"));
|
|
20429
20512
|
return;
|
|
20430
20513
|
}
|
|
@@ -20479,7 +20562,7 @@ init_esm_shims();
|
|
|
20479
20562
|
import { Command as Command11 } from "commander";
|
|
20480
20563
|
import chalk11 from "chalk";
|
|
20481
20564
|
import { readdirSync as readdirSync3, readFileSync as readFileSync12, statSync as statSync4 } from "fs";
|
|
20482
|
-
import { join as
|
|
20565
|
+
import { join as join15, extname as extname3, relative, isAbsolute } from "path";
|
|
20483
20566
|
var SUPPORTED_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
20484
20567
|
".ts",
|
|
20485
20568
|
".tsx",
|
|
@@ -20514,7 +20597,7 @@ function discoverFiles(dir) {
|
|
|
20514
20597
|
}
|
|
20515
20598
|
for (const entry of entries) {
|
|
20516
20599
|
if (entry.startsWith(".")) continue;
|
|
20517
|
-
const full =
|
|
20600
|
+
const full = join15(current, entry);
|
|
20518
20601
|
let stat;
|
|
20519
20602
|
try {
|
|
20520
20603
|
stat = statSync4(full);
|
|
@@ -20605,7 +20688,7 @@ function formatAgent(results, basePath) {
|
|
|
20605
20688
|
const agentResults = [];
|
|
20606
20689
|
for (const r of results) {
|
|
20607
20690
|
if (r.mutations.length === 0 && r.secrets.length === 0) continue;
|
|
20608
|
-
const filePath =
|
|
20691
|
+
const filePath = join15(basePath, r.file);
|
|
20609
20692
|
let lines;
|
|
20610
20693
|
try {
|
|
20611
20694
|
lines = readFileSync12(filePath, "utf-8").split("\n");
|
|
@@ -20676,7 +20759,7 @@ function formatInteractive(results) {
|
|
|
20676
20759
|
}
|
|
20677
20760
|
function reviewCommand() {
|
|
20678
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) => {
|
|
20679
|
-
const targetDir = path2 ? isAbsolute(path2) ? path2 :
|
|
20762
|
+
const targetDir = path2 ? isAbsolute(path2) ? path2 : join15(process.cwd(), path2) : process.cwd();
|
|
20680
20763
|
const files = discoverFiles(targetDir);
|
|
20681
20764
|
if (files.length === 0) {
|
|
20682
20765
|
if (opts?.json || opts?.agent) {
|
|
@@ -20712,13 +20795,13 @@ init_esm_shims();
|
|
|
20712
20795
|
import { Command as Command12 } from "commander";
|
|
20713
20796
|
import chalk12 from "chalk";
|
|
20714
20797
|
import {
|
|
20715
|
-
existsSync as
|
|
20798
|
+
existsSync as existsSync13,
|
|
20716
20799
|
writeFileSync as writeFileSync5,
|
|
20717
20800
|
chmodSync as chmodSync3,
|
|
20718
20801
|
readFileSync as readFileSync13,
|
|
20719
20802
|
mkdirSync as mkdirSync3
|
|
20720
20803
|
} from "fs";
|
|
20721
|
-
import { join as
|
|
20804
|
+
import { join as join16, resolve as resolve4 } from "path";
|
|
20722
20805
|
var HOOK_SCRIPTS = {
|
|
20723
20806
|
"pre-commit": `#!/bin/sh
|
|
20724
20807
|
# Pretense AI Firewall \u2014 pre-commit hook
|
|
@@ -20737,14 +20820,14 @@ exit $?
|
|
|
20737
20820
|
};
|
|
20738
20821
|
var VALID_MODES = ["pre-commit", "pre-push"];
|
|
20739
20822
|
function findGitDir(cwd) {
|
|
20740
|
-
const gitDir =
|
|
20741
|
-
if (
|
|
20823
|
+
const gitDir = join16(cwd, ".git");
|
|
20824
|
+
if (existsSync13(gitDir)) return gitDir;
|
|
20742
20825
|
return null;
|
|
20743
20826
|
}
|
|
20744
20827
|
function installHook(hooksDir, mode, force) {
|
|
20745
|
-
const hookPath =
|
|
20828
|
+
const hookPath = join16(hooksDir, mode);
|
|
20746
20829
|
const script = HOOK_SCRIPTS[mode];
|
|
20747
|
-
if (
|
|
20830
|
+
if (existsSync13(hookPath) && !force) {
|
|
20748
20831
|
const existing = readFileSync13(hookPath, "utf-8");
|
|
20749
20832
|
if (existing.includes("Pretense AI Firewall")) {
|
|
20750
20833
|
return { installed: false, path: hookPath, skipped: true };
|
|
@@ -20786,7 +20869,7 @@ function installCommand() {
|
|
|
20786
20869
|
);
|
|
20787
20870
|
process.exit(1);
|
|
20788
20871
|
}
|
|
20789
|
-
const hooksDir =
|
|
20872
|
+
const hooksDir = join16(gitDir, "hooks");
|
|
20790
20873
|
mkdirSync3(hooksDir, { recursive: true });
|
|
20791
20874
|
console.log(chalk12.cyan("\n Pretense hook installer\n"));
|
|
20792
20875
|
let hasError = false;
|
|
@@ -20823,22 +20906,22 @@ function installCommand() {
|
|
|
20823
20906
|
init_esm_shims();
|
|
20824
20907
|
import { Command as Command13 } from "commander";
|
|
20825
20908
|
import chalk13 from "chalk";
|
|
20826
|
-
import { appendFileSync as appendFileSync3, readFileSync as readFileSync14, existsSync as
|
|
20827
|
-
import { join as
|
|
20909
|
+
import { appendFileSync as appendFileSync3, readFileSync as readFileSync14, existsSync as existsSync14 } from "fs";
|
|
20910
|
+
import { join as join17 } from "path";
|
|
20828
20911
|
import { homedir as homedir8 } from "os";
|
|
20829
20912
|
var IGNORE_FILE = ".pretenseignore";
|
|
20830
|
-
var LAST_SCAN_PATH =
|
|
20913
|
+
var LAST_SCAN_PATH = join17(homedir8(), ".pretense", "last-scan.json");
|
|
20831
20914
|
function ignorePath() {
|
|
20832
|
-
return
|
|
20915
|
+
return join17(process.cwd(), IGNORE_FILE);
|
|
20833
20916
|
}
|
|
20834
20917
|
function readIgnoreFile() {
|
|
20835
20918
|
const p = ignorePath();
|
|
20836
|
-
if (!
|
|
20919
|
+
if (!existsSync14(p)) return [];
|
|
20837
20920
|
return readFileSync14(p, "utf-8").split("\n").filter((l) => l.length > 0);
|
|
20838
20921
|
}
|
|
20839
20922
|
function appendPattern(pattern) {
|
|
20840
20923
|
const p = ignorePath();
|
|
20841
|
-
const content =
|
|
20924
|
+
const content = existsSync14(p) ? readFileSync14(p, "utf-8") : "";
|
|
20842
20925
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
20843
20926
|
if (lines.includes(pattern)) {
|
|
20844
20927
|
console.log(chalk13.yellow(`
|
|
@@ -20877,7 +20960,7 @@ function ignoreCommand() {
|
|
|
20877
20960
|
return;
|
|
20878
20961
|
}
|
|
20879
20962
|
if (opts.lastFound) {
|
|
20880
|
-
if (!
|
|
20963
|
+
if (!existsSync14(LAST_SCAN_PATH)) {
|
|
20881
20964
|
console.error(chalk13.red(`
|
|
20882
20965
|
\u2717 No last scan results found at ${LAST_SCAN_PATH}
|
|
20883
20966
|
`));
|
|
@@ -21135,8 +21218,8 @@ function completionCommand() {
|
|
|
21135
21218
|
init_esm_shims();
|
|
21136
21219
|
import { Command as Command15 } from "commander";
|
|
21137
21220
|
import chalk14 from "chalk";
|
|
21138
|
-
import { existsSync as
|
|
21139
|
-
import { join as
|
|
21221
|
+
import { existsSync as existsSync15, writeFileSync as writeFileSync6 } from "fs";
|
|
21222
|
+
import { join as join18, resolve as resolve5 } from "path";
|
|
21140
21223
|
var DEFAULT_CONFIG_YAML = `scan:
|
|
21141
21224
|
secrets: block
|
|
21142
21225
|
pii: redact
|
|
@@ -21176,9 +21259,9 @@ function quickstartCommand() {
|
|
|
21176
21259
|
process.exit(1);
|
|
21177
21260
|
}
|
|
21178
21261
|
console.log(chalk14.dim(" [2/4] Writing config..."));
|
|
21179
|
-
const configPath =
|
|
21262
|
+
const configPath = join18(dir, "pretense.yaml");
|
|
21180
21263
|
if (!opts.dryRun) {
|
|
21181
|
-
if (!
|
|
21264
|
+
if (!existsSync15(configPath)) {
|
|
21182
21265
|
writeFileSync6(configPath, DEFAULT_CONFIG_YAML);
|
|
21183
21266
|
console.log(chalk14.green(" Created pretense.yaml"));
|
|
21184
21267
|
} else {
|
|
@@ -21187,8 +21270,8 @@ function quickstartCommand() {
|
|
|
21187
21270
|
}
|
|
21188
21271
|
console.log(chalk14.dim(" [3/4] Updating .gitignore..."));
|
|
21189
21272
|
if (!opts.dryRun) {
|
|
21190
|
-
const gitignorePath =
|
|
21191
|
-
let content =
|
|
21273
|
+
const gitignorePath = join18(dir, ".gitignore");
|
|
21274
|
+
let content = existsSync15(gitignorePath) ? (await import("fs")).default.readFileSync(gitignorePath, "utf-8") : "";
|
|
21192
21275
|
if (!content.includes(".pretense/")) {
|
|
21193
21276
|
content = content + (content.endsWith("\n") ? "" : "\n") + ".pretense/\n";
|
|
21194
21277
|
writeFileSync6(gitignorePath, content);
|
|
@@ -21218,7 +21301,7 @@ function quickstartCommand() {
|
|
|
21218
21301
|
init_esm_shims();
|
|
21219
21302
|
import { Command as Command16, Option as Option2 } from "commander";
|
|
21220
21303
|
import chalk16 from "chalk";
|
|
21221
|
-
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";
|
|
21222
21305
|
import { createHash as createHash3 } from "crypto";
|
|
21223
21306
|
import { resolve as resolve6, extname as extname4 } from "path";
|
|
21224
21307
|
|
|
@@ -21226,8 +21309,8 @@ import { resolve as resolve6, extname as extname4 } from "path";
|
|
|
21226
21309
|
init_esm_shims();
|
|
21227
21310
|
import { createCipheriv, createDecipheriv, randomBytes as randomBytes3, hkdfSync as hkdfSync2 } from "crypto";
|
|
21228
21311
|
import { homedir as homedir9 } from "os";
|
|
21229
|
-
import { join as
|
|
21230
|
-
var KEYS_DIR =
|
|
21312
|
+
import { join as join19 } from "path";
|
|
21313
|
+
var KEYS_DIR = join19(homedir9(), ".pretense", "keys");
|
|
21231
21314
|
var HKDF_SALT2 = Buffer.from("pretense-maps-v1", "utf-8");
|
|
21232
21315
|
var HKDF_INFO2 = Buffer.from("secret-mapping-aes-256-gcm", "utf-8");
|
|
21233
21316
|
var IV_LEN = 12;
|
|
@@ -21272,13 +21355,13 @@ import {
|
|
|
21272
21355
|
fchmodSync
|
|
21273
21356
|
} from "fs";
|
|
21274
21357
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
21275
|
-
import { dirname as dirname4, basename as basename2, join as
|
|
21358
|
+
import { dirname as dirname4, basename as basename2, join as join20 } from "path";
|
|
21276
21359
|
function writeFileAtomicSync(targetPath, data, opts = {}) {
|
|
21277
21360
|
let resolved;
|
|
21278
21361
|
try {
|
|
21279
21362
|
resolved = realpathSync2(targetPath);
|
|
21280
21363
|
} catch {
|
|
21281
|
-
resolved =
|
|
21364
|
+
resolved = join20(realpathSync2(dirname4(targetPath)), basename2(targetPath));
|
|
21282
21365
|
}
|
|
21283
21366
|
let mode = opts.mode;
|
|
21284
21367
|
if (mode === void 0) {
|
|
@@ -21289,7 +21372,7 @@ function writeFileAtomicSync(targetPath, data, opts = {}) {
|
|
|
21289
21372
|
}
|
|
21290
21373
|
}
|
|
21291
21374
|
const dir = dirname4(resolved);
|
|
21292
|
-
const tmp =
|
|
21375
|
+
const tmp = join20(dir, `.${basename2(resolved)}.pretense-${randomBytes4(6).toString("hex")}.tmp`);
|
|
21293
21376
|
const buf = Buffer.isBuffer(data) ? data : Buffer.from(data, "utf-8");
|
|
21294
21377
|
let fd = openSync2(tmp, "wx", 384);
|
|
21295
21378
|
try {
|
|
@@ -21330,13 +21413,13 @@ function writeFileAtomicSync(targetPath, data, opts = {}) {
|
|
|
21330
21413
|
// src/default-map.ts
|
|
21331
21414
|
init_esm_shims();
|
|
21332
21415
|
import { createHash as createHash2 } from "crypto";
|
|
21333
|
-
import { join as
|
|
21416
|
+
import { join as join21 } from "path";
|
|
21334
21417
|
function mapsDir(override2) {
|
|
21335
|
-
return override2 ??
|
|
21418
|
+
return override2 ?? join21(pretenseHome(), "maps");
|
|
21336
21419
|
}
|
|
21337
21420
|
function defaultMapPath(absFilePath, override2) {
|
|
21338
21421
|
const digest = createHash2("sha256").update(absFilePath, "utf8").digest("hex");
|
|
21339
|
-
return
|
|
21422
|
+
return join21(mapsDir(override2), `${digest}.json`);
|
|
21340
21423
|
}
|
|
21341
21424
|
function ensureDefaultMapPath(absFilePath, override2) {
|
|
21342
21425
|
ensureDirOwnerOnly(mapsDir(override2));
|
|
@@ -21346,11 +21429,11 @@ function ensureDefaultMapPath(absFilePath, override2) {
|
|
|
21346
21429
|
// src/local-audit.ts
|
|
21347
21430
|
init_esm_shims();
|
|
21348
21431
|
import { homedir as homedir10 } from "os";
|
|
21349
|
-
import { join as
|
|
21432
|
+
import { join as join24 } from "path";
|
|
21350
21433
|
import { randomUUID } from "crypto";
|
|
21351
21434
|
import chalk15 from "chalk";
|
|
21352
21435
|
function localAuditDbPath() {
|
|
21353
|
-
return
|
|
21436
|
+
return join24(homedir10(), ".pretense", "audit.db");
|
|
21354
21437
|
}
|
|
21355
21438
|
function recordLocalAudit(rec, dbPath = localAuditDbPath()) {
|
|
21356
21439
|
let store = null;
|
|
@@ -21449,7 +21532,7 @@ async function uploadUsage(event) {
|
|
|
21449
21532
|
// src/commands/mutate.ts
|
|
21450
21533
|
var REVERSAL_MAP_VERSION = 3;
|
|
21451
21534
|
function preflightReversalMap(mapPath, absFile, content, contentSha, force) {
|
|
21452
|
-
if (!
|
|
21535
|
+
if (!existsSync16(mapPath)) return { action: "write", generation: 1 };
|
|
21453
21536
|
let existing;
|
|
21454
21537
|
try {
|
|
21455
21538
|
const parsed = JSON.parse(readFileSync15(mapPath, "utf-8"));
|
|
@@ -21626,7 +21709,25 @@ async function runMutate(file, opts = {}) {
|
|
|
21626
21709
|
opts.level,
|
|
21627
21710
|
opts.presetName
|
|
21628
21711
|
);
|
|
21629
|
-
|
|
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) {
|
|
21630
21731
|
if (unmutatable.size === 0) {
|
|
21631
21732
|
console.error(chalk16.dim(` No secrets found in ${file} \u2014 nothing to mutate.`));
|
|
21632
21733
|
} else {
|
|
@@ -21636,9 +21737,10 @@ async function runMutate(file, opts = {}) {
|
|
|
21636
21737
|
return 0;
|
|
21637
21738
|
}
|
|
21638
21739
|
reportUnmutatable(unmutatable);
|
|
21639
|
-
const
|
|
21640
|
-
|
|
21641
|
-
|
|
21740
|
+
const result = {
|
|
21741
|
+
content: finalContent,
|
|
21742
|
+
mutations: [...secretResult.mutations, ...identifierMutations]
|
|
21743
|
+
};
|
|
21642
21744
|
let effectiveMap;
|
|
21643
21745
|
if (preview) {
|
|
21644
21746
|
effectiveMap = void 0;
|
|
@@ -21710,13 +21812,21 @@ async function runMutate(file, opts = {}) {
|
|
|
21710
21812
|
);
|
|
21711
21813
|
return 1;
|
|
21712
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
|
+
};
|
|
21713
21823
|
try {
|
|
21714
21824
|
if (inPlace) {
|
|
21715
21825
|
writeFileAtomicSync(file, result.content);
|
|
21716
|
-
console.error(chalk16.green(` \u2713 Mutated ${
|
|
21826
|
+
console.error(chalk16.green(` \u2713 Mutated ${summary()} in ${file} (in-place)`));
|
|
21717
21827
|
} else if (opts.output) {
|
|
21718
21828
|
writeFileAtomicSync(opts.output, result.content);
|
|
21719
|
-
console.error(chalk16.green(` \u2713 Mutated ${
|
|
21829
|
+
console.error(chalk16.green(` \u2713 Mutated ${summary()} \u2192 ${opts.output}`));
|
|
21720
21830
|
} else {
|
|
21721
21831
|
process.stdout.write(result.content);
|
|
21722
21832
|
}
|
|
@@ -21733,7 +21843,9 @@ async function runMutate(file, opts = {}) {
|
|
|
21733
21843
|
let secretsBlocked = 0;
|
|
21734
21844
|
let piiRedacted = 0;
|
|
21735
21845
|
for (const m of result.mutations) {
|
|
21736
|
-
|
|
21846
|
+
const cat = categoryByType.get(m.type);
|
|
21847
|
+
if (cat === "pii") piiRedacted += 1;
|
|
21848
|
+
else if (m.type === "proprietary") continue;
|
|
21737
21849
|
else secretsBlocked += 1;
|
|
21738
21850
|
}
|
|
21739
21851
|
recordLocalAudit({
|
|
@@ -21795,7 +21907,7 @@ function mutateCommand() {
|
|
|
21795
21907
|
init_esm_shims();
|
|
21796
21908
|
import { Command as Command17 } from "commander";
|
|
21797
21909
|
import chalk17 from "chalk";
|
|
21798
|
-
import { readFileSync as readFileSync16, existsSync as
|
|
21910
|
+
import { readFileSync as readFileSync16, existsSync as existsSync17, statSync as statSync6 } from "fs";
|
|
21799
21911
|
import { resolve as resolve7 } from "path";
|
|
21800
21912
|
import { createHash as createHash4 } from "crypto";
|
|
21801
21913
|
function sha256Hex3(s) {
|
|
@@ -21856,14 +21968,14 @@ function loadReversalMap(mapPath) {
|
|
|
21856
21968
|
function runReverse(file, opts = {}) {
|
|
21857
21969
|
const reverseStartMs = Date.now();
|
|
21858
21970
|
const absPath = resolve7(file);
|
|
21859
|
-
if (!
|
|
21971
|
+
if (!existsSync17(absPath) || !statSync6(absPath).isFile()) {
|
|
21860
21972
|
console.error(chalk17.red(`
|
|
21861
21973
|
x File not found: ${file}
|
|
21862
21974
|
`));
|
|
21863
21975
|
return 1;
|
|
21864
21976
|
}
|
|
21865
21977
|
const mapPath = opts.map ?? defaultMapPath(absPath, opts.mapsDir);
|
|
21866
|
-
if (!opts.map && !
|
|
21978
|
+
if (!opts.map && !existsSync17(mapPath)) {
|
|
21867
21979
|
console.error(
|
|
21868
21980
|
chalk17.red(`
|
|
21869
21981
|
x No reversal map found for ${absPath}`) + chalk17.dim(`
|
|
@@ -22320,7 +22432,7 @@ init_esm_shims();
|
|
|
22320
22432
|
import { Command as Command20 } from "commander";
|
|
22321
22433
|
import chalk20 from "chalk";
|
|
22322
22434
|
import { homedir as homedir11 } from "os";
|
|
22323
|
-
import { join as
|
|
22435
|
+
import { join as join25 } from "path";
|
|
22324
22436
|
var VALID_FORMATS2 = ["table", "csv", "json", "jsonl"];
|
|
22325
22437
|
function toSafeAuditRow(e) {
|
|
22326
22438
|
return {
|
|
@@ -22444,7 +22556,7 @@ function auditCommand() {
|
|
|
22444
22556
|
`));
|
|
22445
22557
|
process.exit(1);
|
|
22446
22558
|
}
|
|
22447
|
-
const dbPath = opts.db ??
|
|
22559
|
+
const dbPath = opts.db ?? join25(homedir11(), ".pretense", "audit.db");
|
|
22448
22560
|
let rows;
|
|
22449
22561
|
try {
|
|
22450
22562
|
const store = new AuditStore(dbPath);
|
|
@@ -22504,7 +22616,7 @@ function auditCommand() {
|
|
|
22504
22616
|
init_esm_shims();
|
|
22505
22617
|
import { Command as Command21 } from "commander";
|
|
22506
22618
|
import chalk21 from "chalk";
|
|
22507
|
-
import { join as
|
|
22619
|
+
import { join as join26 } from "path";
|
|
22508
22620
|
import { homedir as homedir12 } from "os";
|
|
22509
22621
|
function remaining(used, limit) {
|
|
22510
22622
|
if (limit === null) return null;
|
|
@@ -22523,7 +22635,7 @@ function bar(used, limit, width = 24) {
|
|
|
22523
22635
|
return chalk21.green(s);
|
|
22524
22636
|
}
|
|
22525
22637
|
function creditsCommand() {
|
|
22526
|
-
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) => {
|
|
22527
22639
|
const resolution = await resolvePlanTier({ offline: opts.offline });
|
|
22528
22640
|
const tier = resolution.tier;
|
|
22529
22641
|
const collected = collectUsage(opts.db);
|
package/dist/postinstall.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pretense/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.21",
|
|
4
4
|
"description": "Local-first AI firewall that mutates proprietary code before sending to LLM APIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
"typescript": "^5.4.0",
|
|
25
25
|
"vitest": "^1.0.0",
|
|
26
26
|
"@pretense/billing": "0.1.0",
|
|
27
|
+
"@pretense/compliance-engine": "0.1.0",
|
|
27
28
|
"@pretense/protocol": "0.1.0",
|
|
28
29
|
"@pretense/learner": "0.2.0",
|
|
29
30
|
"@pretense/mutator": "0.2.0",
|
|
30
|
-
"@pretense/
|
|
31
|
+
"@pretense/proxy": "0.1.0",
|
|
31
32
|
"@pretense/scanner": "0.2.0",
|
|
32
33
|
"@pretense/scanner-rs": "0.2.0",
|
|
33
|
-
"@pretense/store": "0.2.0"
|
|
34
|
-
"@pretense/proxy": "0.1.0"
|
|
34
|
+
"@pretense/store": "0.2.0"
|
|
35
35
|
},
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public",
|