@pretense/cli 0.6.2 → 0.6.5
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-TWMRHZGM.js +0 -0
- package/dist/ed25519-XYI7WRQL.js +0 -0
- package/dist/index.js +106 -463
- package/dist/postinstall.js +0 -0
- package/package.json +18 -19
package/dist/chunk-TWMRHZGM.js
CHANGED
|
File without changes
|
package/dist/ed25519-XYI7WRQL.js
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
@@ -10385,7 +10385,6 @@ function listPresetIds() {
|
|
|
10385
10385
|
|
|
10386
10386
|
// ../packages/scanner/dist/index.js
|
|
10387
10387
|
import { gunzipSync } from "zlib";
|
|
10388
|
-
import { createRequire } from "module";
|
|
10389
10388
|
var SECRET_LABEL_TAILS = [
|
|
10390
10389
|
// password family
|
|
10391
10390
|
"password",
|
|
@@ -13279,259 +13278,6 @@ function resolveSafeSpan(original, map, viewStart, viewEnd, value, cost) {
|
|
|
13279
13278
|
if (!spanContainsValue(slice, value, cost)) return null;
|
|
13280
13279
|
return { start, end, value: slice };
|
|
13281
13280
|
}
|
|
13282
|
-
var _native;
|
|
13283
|
-
function loadNative() {
|
|
13284
|
-
if (_native !== void 0) return _native;
|
|
13285
|
-
try {
|
|
13286
|
-
const require2 = createRequire(import.meta.url);
|
|
13287
|
-
const mod = require2("@pretense/scanner-rs");
|
|
13288
|
-
if (typeof mod?.semanticScan !== "function") {
|
|
13289
|
-
_native = null;
|
|
13290
|
-
} else {
|
|
13291
|
-
_native = mod;
|
|
13292
|
-
}
|
|
13293
|
-
} catch {
|
|
13294
|
-
_native = null;
|
|
13295
|
-
}
|
|
13296
|
-
return _native;
|
|
13297
|
-
}
|
|
13298
|
-
var _astProbe;
|
|
13299
|
-
function isAstCoreAvailable() {
|
|
13300
|
-
if (_astProbe !== void 0) return _astProbe;
|
|
13301
|
-
const native = loadNative();
|
|
13302
|
-
if (!native) {
|
|
13303
|
-
_astProbe = false;
|
|
13304
|
-
return false;
|
|
13305
|
-
}
|
|
13306
|
-
try {
|
|
13307
|
-
native.semanticScan("", "typescript");
|
|
13308
|
-
_astProbe = true;
|
|
13309
|
-
} catch {
|
|
13310
|
-
_astProbe = false;
|
|
13311
|
-
}
|
|
13312
|
-
return _astProbe;
|
|
13313
|
-
}
|
|
13314
|
-
function makeByteToChar(text) {
|
|
13315
|
-
let ascii = true;
|
|
13316
|
-
for (let i = 0; i < text.length; i++) {
|
|
13317
|
-
if (text.charCodeAt(i) > 127) {
|
|
13318
|
-
ascii = false;
|
|
13319
|
-
break;
|
|
13320
|
-
}
|
|
13321
|
-
}
|
|
13322
|
-
if (ascii) return (b) => b;
|
|
13323
|
-
const totalBytes = Buffer.byteLength(text, "utf8");
|
|
13324
|
-
const table = new Int32Array(totalBytes + 1);
|
|
13325
|
-
let byte = 0;
|
|
13326
|
-
for (let charIdx = 0; charIdx < text.length; ) {
|
|
13327
|
-
const cp = text.codePointAt(charIdx);
|
|
13328
|
-
const unitLen = cp > 65535 ? 2 : 1;
|
|
13329
|
-
const byteLen = Buffer.byteLength(String.fromCodePoint(cp), "utf8");
|
|
13330
|
-
for (let k = 0; k < byteLen; k++) table[byte + k] = charIdx;
|
|
13331
|
-
byte += byteLen;
|
|
13332
|
-
charIdx += unitLen;
|
|
13333
|
-
}
|
|
13334
|
-
table[totalBytes] = text.length;
|
|
13335
|
-
return (b) => {
|
|
13336
|
-
if (b <= 0) return 0;
|
|
13337
|
-
if (b >= totalBytes) return text.length;
|
|
13338
|
-
return table[b];
|
|
13339
|
-
};
|
|
13340
|
-
}
|
|
13341
|
-
function isInsideAnySpan(start, end, spans) {
|
|
13342
|
-
for (const s of spans) {
|
|
13343
|
-
if (s.start > start) break;
|
|
13344
|
-
if (start >= s.start && end <= s.end) return true;
|
|
13345
|
-
}
|
|
13346
|
-
return false;
|
|
13347
|
-
}
|
|
13348
|
-
var CREDENTIAL_NAME = /(?:^|[._-]|(?<=[a-z0-9]))(?:api[_-]?key|api[_-]?secret|secret|secrets|token|password|passwd|pwd|access[_-]?key|access[_-]?token|private[_-]?key|client[_-]?secret|auth[_-]?token|bearer[_-]?token|session[_-]?secret|encryption[_-]?key|signing[_-]?key)s?$/i;
|
|
13349
|
-
var CREDENTIAL_SETTER = /^(?:set|with|configure|use|update|put|load|init)[_-]?(?:api[_-]?key|api[_-]?secret|secret|token|password|passwd|pwd|access[_-]?key|access[_-]?token|private[_-]?key|client[_-]?secret|auth[_-]?token|bearer[_-]?token|credential|credentials|key)s?$/i;
|
|
13350
|
-
function looksLikeCredentialName(name) {
|
|
13351
|
-
return CREDENTIAL_NAME.test(name);
|
|
13352
|
-
}
|
|
13353
|
-
function looksLikeCredentialSetter(callee) {
|
|
13354
|
-
const last = callee.split(".").pop() ?? callee;
|
|
13355
|
-
return CREDENTIAL_SETTER.test(last);
|
|
13356
|
-
}
|
|
13357
|
-
function unquoteLiteral(literal) {
|
|
13358
|
-
const t = literal.trim();
|
|
13359
|
-
if (t.length < 2) return null;
|
|
13360
|
-
const open = t[0];
|
|
13361
|
-
const close = t[t.length - 1];
|
|
13362
|
-
if (open === '"' && close === '"' || open === "'" && close === "'" || open === "`" && close === "`") {
|
|
13363
|
-
return t.slice(1, -1);
|
|
13364
|
-
}
|
|
13365
|
-
const firstQuote = t.search(/["'`]/);
|
|
13366
|
-
if (firstQuote >= 0) {
|
|
13367
|
-
const q = t[firstQuote];
|
|
13368
|
-
const lastQuote = t.lastIndexOf(q);
|
|
13369
|
-
if (lastQuote > firstQuote) return t.slice(firstQuote + 1, lastQuote);
|
|
13370
|
-
}
|
|
13371
|
-
return null;
|
|
13372
|
-
}
|
|
13373
|
-
var STRING_LITERAL_RX = /^\s*["'`]/;
|
|
13374
|
-
function dataFlowMatches(text, sem, nextId2) {
|
|
13375
|
-
const matches = [];
|
|
13376
|
-
const findings = [];
|
|
13377
|
-
for (const edge of sem.edges) {
|
|
13378
|
-
const isAssign = edge.kind === "Assignment" && looksLikeCredentialName(edge.from);
|
|
13379
|
-
const isSetter = edge.kind === "Call" && looksLikeCredentialSetter(edge.from);
|
|
13380
|
-
if (!isAssign && !isSetter) continue;
|
|
13381
|
-
if (!STRING_LITERAL_RX.test(edge.to)) continue;
|
|
13382
|
-
const inner = unquoteLiteral(edge.to);
|
|
13383
|
-
if (inner === null || inner.length === 0) continue;
|
|
13384
|
-
const span = locateLiteral(text, edge.to, edge.line);
|
|
13385
|
-
const start = span && span.start >= 0 ? span.start : 0;
|
|
13386
|
-
const end = span && span.end >= 0 ? span.end : 0;
|
|
13387
|
-
const severity = "high";
|
|
13388
|
-
const category = "secret";
|
|
13389
|
-
const action = "redact";
|
|
13390
|
-
const type = "dataflow-credential";
|
|
13391
|
-
const id = nextId2();
|
|
13392
|
-
const masked = maskCredential(inner);
|
|
13393
|
-
matches.push({ id, category, type, value: inner, masked, start, end, severity, action, confidence: 0.85 });
|
|
13394
|
-
findings.push({
|
|
13395
|
-
ruleId: type,
|
|
13396
|
-
value: inner,
|
|
13397
|
-
masked,
|
|
13398
|
-
severity,
|
|
13399
|
-
category,
|
|
13400
|
-
line: edge.line,
|
|
13401
|
-
column: span?.column ?? 0,
|
|
13402
|
-
start,
|
|
13403
|
-
end,
|
|
13404
|
-
action,
|
|
13405
|
-
confidence: 0.85
|
|
13406
|
-
});
|
|
13407
|
-
}
|
|
13408
|
-
return { matches, findings };
|
|
13409
|
-
}
|
|
13410
|
-
function maskCredential(value) {
|
|
13411
|
-
if (value.length <= 8) return "***";
|
|
13412
|
-
return value.slice(0, 4) + "..." + value.slice(-4);
|
|
13413
|
-
}
|
|
13414
|
-
function locateLiteral(text, literalSource, line) {
|
|
13415
|
-
let lineStart = 0;
|
|
13416
|
-
let curLine = 1;
|
|
13417
|
-
for (let i = 0; i < text.length && curLine < line; i++) {
|
|
13418
|
-
if (text.charCodeAt(i) === 10) {
|
|
13419
|
-
curLine++;
|
|
13420
|
-
lineStart = i + 1;
|
|
13421
|
-
}
|
|
13422
|
-
}
|
|
13423
|
-
let idx = text.indexOf(literalSource, lineStart);
|
|
13424
|
-
if (idx < 0) idx = text.indexOf(literalSource);
|
|
13425
|
-
if (idx < 0) return null;
|
|
13426
|
-
const lineNlBefore = text.lastIndexOf("\n", idx);
|
|
13427
|
-
const column = lineNlBefore < 0 ? idx : idx - lineNlBefore - 1;
|
|
13428
|
-
return { start: idx, end: idx + literalSource.length, column };
|
|
13429
|
-
}
|
|
13430
|
-
var SEVERITY_RANK = { critical: 4, high: 3, medium: 2, low: 1 };
|
|
13431
|
-
function rebuildFindings(matches, findingsByMatchId) {
|
|
13432
|
-
const out = [];
|
|
13433
|
-
for (const m of matches) {
|
|
13434
|
-
const f = findingsByMatchId.get(m.id);
|
|
13435
|
-
if (f) out.push(f);
|
|
13436
|
-
}
|
|
13437
|
-
return out;
|
|
13438
|
-
}
|
|
13439
|
-
function dedupeMatches(matches) {
|
|
13440
|
-
const sorted = [...matches].sort(
|
|
13441
|
-
(a, b) => a.start - b.start || SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity] || b.confidence - a.confidence
|
|
13442
|
-
);
|
|
13443
|
-
const kept = [];
|
|
13444
|
-
for (const m of sorted) {
|
|
13445
|
-
const overlap = kept.find(
|
|
13446
|
-
(k) => m.start < k.end && k.start < m.end && !(m.start === 0 && m.end === 0)
|
|
13447
|
-
);
|
|
13448
|
-
if (!overlap) {
|
|
13449
|
-
kept.push(m);
|
|
13450
|
-
}
|
|
13451
|
-
}
|
|
13452
|
-
const seenZero = /* @__PURE__ */ new Set();
|
|
13453
|
-
return kept.filter((m) => {
|
|
13454
|
-
if (m.start === 0 && m.end === 0) {
|
|
13455
|
-
const key = `${m.type}:${m.value}`;
|
|
13456
|
-
if (seenZero.has(key)) return false;
|
|
13457
|
-
seenZero.add(key);
|
|
13458
|
-
}
|
|
13459
|
-
return true;
|
|
13460
|
-
});
|
|
13461
|
-
}
|
|
13462
|
-
async function scanLevel2(text, language, opts = {}) {
|
|
13463
|
-
const lang = language ?? opts.language ?? "typescript";
|
|
13464
|
-
const base = opts.presidioUrl ? await scanWithPresidio(text, opts.presidioUrl, opts) : scan(text, opts);
|
|
13465
|
-
const native = loadNative();
|
|
13466
|
-
if (!native) return base;
|
|
13467
|
-
let sem;
|
|
13468
|
-
try {
|
|
13469
|
-
sem = native.semanticScan(text, lang);
|
|
13470
|
-
} catch {
|
|
13471
|
-
return base;
|
|
13472
|
-
}
|
|
13473
|
-
const byteToChar = makeByteToChar(text);
|
|
13474
|
-
const commentSpans = [];
|
|
13475
|
-
for (const node of sem.nodes) {
|
|
13476
|
-
if (node.class === "Comment") {
|
|
13477
|
-
commentSpans.push({ start: byteToChar(node.start_byte), end: byteToChar(node.end_byte) });
|
|
13478
|
-
}
|
|
13479
|
-
}
|
|
13480
|
-
commentSpans.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
13481
|
-
const findingsById = /* @__PURE__ */ new Map();
|
|
13482
|
-
base.matches.forEach((m, i) => findingsById.set(m.id, base.findings[i] ?? toFinding(text, m)));
|
|
13483
|
-
const survivingMatches = base.matches.filter(
|
|
13484
|
-
(m) => m.start === m.end || !isInsideAnySpan(m.start, m.end, commentSpans)
|
|
13485
|
-
);
|
|
13486
|
-
let dfMatches = [];
|
|
13487
|
-
if (opts.dataFlow !== false) {
|
|
13488
|
-
let counter = 0;
|
|
13489
|
-
const nextId2 = () => `l2df_${++counter}`;
|
|
13490
|
-
const df = dataFlowMatches(text, sem, nextId2);
|
|
13491
|
-
df.matches.forEach((m, i) => findingsById.set(m.id, df.findings[i] ?? toFinding(text, m)));
|
|
13492
|
-
dfMatches = df.matches.filter((m) => !isInsideAnySpan(m.start, m.end, commentSpans));
|
|
13493
|
-
}
|
|
13494
|
-
const deduped = dedupeMatches([...survivingMatches, ...dfMatches]).sort(
|
|
13495
|
-
(a, b) => a.start - b.start || SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity]
|
|
13496
|
-
);
|
|
13497
|
-
const dedupedFindings = rebuildFindings(deduped, findingsById).sort(
|
|
13498
|
-
(a, b) => a.start - b.start || SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity]
|
|
13499
|
-
);
|
|
13500
|
-
const clean = deduped.filter((m) => m.action === "block" || m.action === "redact").length === 0;
|
|
13501
|
-
return {
|
|
13502
|
-
clean,
|
|
13503
|
-
matches: deduped,
|
|
13504
|
-
findings: dedupedFindings,
|
|
13505
|
-
scannedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13506
|
-
durationMs: base.durationMs,
|
|
13507
|
-
patternCount: base.patternCount,
|
|
13508
|
-
// Bounded-work state is a property of the underlying scan and MUST survive
|
|
13509
|
-
// this merge — dropping it here would re-create the silent-incomplete hole
|
|
13510
|
-
// one layer up.
|
|
13511
|
-
incomplete: base.incomplete,
|
|
13512
|
-
limits: base.limits
|
|
13513
|
-
};
|
|
13514
|
-
}
|
|
13515
|
-
function toFinding(text, m) {
|
|
13516
|
-
const before = text.slice(0, m.start);
|
|
13517
|
-
const line = (before.match(/\n/g) ?? []).length + 1;
|
|
13518
|
-
const lastNl = before.lastIndexOf("\n");
|
|
13519
|
-
const column = lastNl === -1 ? m.start : m.start - lastNl - 1;
|
|
13520
|
-
return {
|
|
13521
|
-
ruleId: m.type,
|
|
13522
|
-
value: m.value,
|
|
13523
|
-
masked: m.masked,
|
|
13524
|
-
severity: m.severity,
|
|
13525
|
-
category: m.category,
|
|
13526
|
-
line,
|
|
13527
|
-
column,
|
|
13528
|
-
start: m.start,
|
|
13529
|
-
end: m.end,
|
|
13530
|
-
action: m.action,
|
|
13531
|
-
confidence: m.confidence,
|
|
13532
|
-
...m.entropy !== void 0 ? { entropy: m.entropy } : {}
|
|
13533
|
-
};
|
|
13534
|
-
}
|
|
13535
13281
|
var MIN_SPAN_VERIFY_CHARS = 1024 * 1024;
|
|
13536
13282
|
var MAX_SPAN_VERIFY_CHARS = 256 * 1024 * 1024;
|
|
13537
13283
|
var SPAN_VERIFY_CHARS_PER_CHAR = 64;
|
|
@@ -13878,60 +13624,6 @@ function scan(text, opts = {}) {
|
|
|
13878
13624
|
limits
|
|
13879
13625
|
};
|
|
13880
13626
|
}
|
|
13881
|
-
async function scanWithPresidio(text, presidioUrl, opts = {}) {
|
|
13882
|
-
const { presidio: _presidio, ...syncOpts } = opts;
|
|
13883
|
-
const base = scan(text, syncOpts);
|
|
13884
|
-
const nlIndex = buildNewlineIndex(text);
|
|
13885
|
-
try {
|
|
13886
|
-
const resp = await fetch(`${presidioUrl}/analyze`, {
|
|
13887
|
-
method: "POST",
|
|
13888
|
-
headers: { "Content-Type": "application/json" },
|
|
13889
|
-
body: JSON.stringify({ text, language: "en" }),
|
|
13890
|
-
signal: AbortSignal.timeout(2e3)
|
|
13891
|
-
});
|
|
13892
|
-
if (!resp.ok) return base;
|
|
13893
|
-
const presidioResults = await resp.json();
|
|
13894
|
-
for (const pr of presidioResults) {
|
|
13895
|
-
const alreadyCovered = base.matches.some((m) => m.start <= pr.start && m.end >= pr.end);
|
|
13896
|
-
if (!alreadyCovered && pr.score >= 0.7) {
|
|
13897
|
-
const value = text.slice(pr.start, pr.end);
|
|
13898
|
-
const type = `presidio-${pr.entity_type.toLowerCase()}`;
|
|
13899
|
-
const severity = pr.score >= 0.9 ? "high" : "medium";
|
|
13900
|
-
base.matches.push({
|
|
13901
|
-
id: nextId(),
|
|
13902
|
-
category: "pii",
|
|
13903
|
-
type,
|
|
13904
|
-
value,
|
|
13905
|
-
masked: "***",
|
|
13906
|
-
start: pr.start,
|
|
13907
|
-
end: pr.end,
|
|
13908
|
-
severity,
|
|
13909
|
-
action: "redact",
|
|
13910
|
-
confidence: pr.score
|
|
13911
|
-
});
|
|
13912
|
-
const { line, column } = lineColFromOffset(text, pr.start, nlIndex);
|
|
13913
|
-
base.findings.push({
|
|
13914
|
-
ruleId: type,
|
|
13915
|
-
value,
|
|
13916
|
-
masked: "***",
|
|
13917
|
-
severity,
|
|
13918
|
-
category: "pii",
|
|
13919
|
-
line,
|
|
13920
|
-
column,
|
|
13921
|
-
start: pr.start,
|
|
13922
|
-
end: pr.end,
|
|
13923
|
-
action: "redact",
|
|
13924
|
-
confidence: pr.score
|
|
13925
|
-
});
|
|
13926
|
-
}
|
|
13927
|
-
}
|
|
13928
|
-
base.matches.sort((a, b) => a.start - b.start);
|
|
13929
|
-
base.findings.sort((a, b) => a.start - b.start);
|
|
13930
|
-
base.clean = base.matches.filter((m) => m.action === "block" || m.action === "redact").length === 0;
|
|
13931
|
-
} catch {
|
|
13932
|
-
}
|
|
13933
|
-
return base;
|
|
13934
|
-
}
|
|
13935
13627
|
|
|
13936
13628
|
// ../packages/mutator/dist/index.js
|
|
13937
13629
|
init_esm_shims();
|
|
@@ -15862,6 +15554,30 @@ function extractDeltas(line, provider) {
|
|
|
15862
15554
|
delta[prop] = v;
|
|
15863
15555
|
}
|
|
15864
15556
|
});
|
|
15557
|
+
} else if (provider === "google") {
|
|
15558
|
+
const candidates = json["candidates"];
|
|
15559
|
+
if (!Array.isArray(candidates)) return null;
|
|
15560
|
+
for (let ci = 0; ci < candidates.length; ci++) {
|
|
15561
|
+
const cand = candidates[ci];
|
|
15562
|
+
const candIndex = typeof cand["index"] === "number" ? cand["index"] : ci;
|
|
15563
|
+
const content = cand["content"];
|
|
15564
|
+
if (!content) continue;
|
|
15565
|
+
const parts = content["parts"];
|
|
15566
|
+
if (!Array.isArray(parts)) continue;
|
|
15567
|
+
for (const part of parts) {
|
|
15568
|
+
if (typeof part["text"] !== "string") continue;
|
|
15569
|
+
const isThought = part["thought"] === true;
|
|
15570
|
+
refs.push({
|
|
15571
|
+
key: `g:${candIndex}:${isThought ? "thought" : "text"}`,
|
|
15572
|
+
index: candIndex,
|
|
15573
|
+
kind: isThought ? "google_thought" : "google_text",
|
|
15574
|
+
text: part["text"],
|
|
15575
|
+
set: (v) => {
|
|
15576
|
+
part["text"] = v;
|
|
15577
|
+
}
|
|
15578
|
+
});
|
|
15579
|
+
}
|
|
15580
|
+
}
|
|
15865
15581
|
} else {
|
|
15866
15582
|
const choices = json["choices"];
|
|
15867
15583
|
if (!Array.isArray(choices) || choices.length === 0) return null;
|
|
@@ -15907,6 +15623,14 @@ function toJsonStringContextMap(map) {
|
|
|
15907
15623
|
}
|
|
15908
15624
|
return out;
|
|
15909
15625
|
}
|
|
15626
|
+
function classifyStreamProvider(upstream) {
|
|
15627
|
+
const u = upstream.toLowerCase();
|
|
15628
|
+
if (u.includes("anthropic")) return "anthropic";
|
|
15629
|
+
if (u.includes("generativelanguage") || u.includes("googleapis") || u.includes("gemini")) {
|
|
15630
|
+
return "google";
|
|
15631
|
+
}
|
|
15632
|
+
return "openai";
|
|
15633
|
+
}
|
|
15910
15634
|
async function streamWithRollingBuffer(upstreamResp, map, provider, requestId) {
|
|
15911
15635
|
const buffers = /* @__PURE__ */ new Map();
|
|
15912
15636
|
const bufferMeta = /* @__PURE__ */ new Map();
|
|
@@ -16021,6 +15745,12 @@ function buildFlushEvent(text, provider, kind, index) {
|
|
|
16021
15745
|
const delta2 = kind === "input_json" ? { type: "input_json_delta", partial_json: text } : kind === "thinking" ? { type: "thinking_delta", thinking: text } : { type: "text_delta", text };
|
|
16022
15746
|
return "data: " + JSON.stringify({ type: "content_block_delta", index, delta: delta2 });
|
|
16023
15747
|
}
|
|
15748
|
+
if (provider === "google") {
|
|
15749
|
+
const part = kind === "google_thought" ? { text, thought: true } : { text };
|
|
15750
|
+
return "data: " + JSON.stringify({
|
|
15751
|
+
candidates: [{ content: { parts: [part], role: "model" }, index }]
|
|
15752
|
+
});
|
|
15753
|
+
}
|
|
16024
15754
|
const delta = kind === "openai_tool_args" ? { tool_calls: [{ index, function: { arguments: text } }] } : { content: text };
|
|
16025
15755
|
return "data: " + JSON.stringify({
|
|
16026
15756
|
id: "pretense-flush",
|
|
@@ -16276,7 +16006,7 @@ function tokenizeBodyDeep(body, scanText) {
|
|
|
16276
16006
|
};
|
|
16277
16007
|
}
|
|
16278
16008
|
async function handleStreaming(upstreamResp, map, requestId, upstream) {
|
|
16279
|
-
const provider = upstream
|
|
16009
|
+
const provider = classifyStreamProvider(upstream);
|
|
16280
16010
|
return streamWithRollingBuffer(upstreamResp, map, provider, requestId);
|
|
16281
16011
|
}
|
|
16282
16012
|
function createProxy(opts = {}) {
|
|
@@ -16750,7 +16480,10 @@ Upgrade to ${_upgradeTier === "enterprise" ? "Enterprise" : "Pro"} for ${_upgrad
|
|
|
16750
16480
|
for (const [orig, syn] of globalMap.entries()) {
|
|
16751
16481
|
if (!secretMap.has(syn)) reverseMap.set(orig, syn);
|
|
16752
16482
|
}
|
|
16753
|
-
|
|
16483
|
+
const upstreamIsSse = (upstreamResp.headers.get("content-type") ?? "").includes(
|
|
16484
|
+
"text/event-stream"
|
|
16485
|
+
);
|
|
16486
|
+
if (body["stream"] === true || upstreamIsSse) {
|
|
16754
16487
|
return handleStreaming(upstreamResp, reverseMap, requestId, upstream);
|
|
16755
16488
|
}
|
|
16756
16489
|
let respBody;
|
|
@@ -16987,71 +16720,13 @@ function filterExisting(files) {
|
|
|
16987
16720
|
}
|
|
16988
16721
|
});
|
|
16989
16722
|
}
|
|
16990
|
-
function langForFile(filePath) {
|
|
16991
|
-
switch (filePath ? extname2(filePath).toLowerCase() : "") {
|
|
16992
|
-
case ".py":
|
|
16993
|
-
return "python";
|
|
16994
|
-
case ".go":
|
|
16995
|
-
return "go";
|
|
16996
|
-
case ".java":
|
|
16997
|
-
return "java";
|
|
16998
|
-
case ".rb":
|
|
16999
|
-
return "ruby";
|
|
17000
|
-
case ".rs":
|
|
17001
|
-
return "rust";
|
|
17002
|
-
case ".cs":
|
|
17003
|
-
return "csharp";
|
|
17004
|
-
case ".js":
|
|
17005
|
-
case ".jsx":
|
|
17006
|
-
return "javascript";
|
|
17007
|
-
case ".tsx":
|
|
17008
|
-
case ".ts":
|
|
17009
|
-
return "typescript";
|
|
17010
|
-
default:
|
|
17011
|
-
return "typescript";
|
|
17012
|
-
}
|
|
17013
|
-
}
|
|
17014
|
-
function resolveScanLevel(opts) {
|
|
17015
|
-
if (opts.ast) return 2;
|
|
17016
|
-
const raw2 = opts.level;
|
|
17017
|
-
if (raw2 === void 0 || raw2 === "1") return 1;
|
|
17018
|
-
if (raw2 === "2") return 2;
|
|
17019
|
-
console.error(chalk3.red(`
|
|
17020
|
-
x Invalid --level: "${raw2}". Use 1 (regex) or 2 (AST/data-flow).
|
|
17021
|
-
`));
|
|
17022
|
-
process.exit(1);
|
|
17023
|
-
}
|
|
17024
|
-
var _astFallbackNoticePrinted = false;
|
|
17025
|
-
function resolveLevelWithAst(opts) {
|
|
17026
|
-
const level = resolveScanLevel(opts);
|
|
17027
|
-
if (level === 1) return { level, astUsed: false };
|
|
17028
|
-
const astUsed = isAstCoreAvailable();
|
|
17029
|
-
if (!astUsed && !_astFallbackNoticePrinted) {
|
|
17030
|
-
console.error(
|
|
17031
|
-
chalk3.yellow("\n ! AST core (@pretense/scanner-rs) unavailable \u2014 falling back to L1 (regex).") + chalk3.dim("\n Build the native core to enable L2 data-flow detection.\n")
|
|
17032
|
-
);
|
|
17033
|
-
_astFallbackNoticePrinted = true;
|
|
17034
|
-
}
|
|
17035
|
-
return { level, astUsed };
|
|
17036
|
-
}
|
|
17037
|
-
function effectiveScanLevel(requested, astUsed) {
|
|
17038
|
-
return requested === 2 && astUsed ? 2 : 1;
|
|
17039
|
-
}
|
|
17040
|
-
function levelLabel(level, astUsed) {
|
|
17041
|
-
if (level === 1) return "L1 \xB7 regex";
|
|
17042
|
-
return astUsed ? "L2 \xB7 AST + regex" : "L2 \u2192 L1 (AST unavailable)";
|
|
17043
|
-
}
|
|
17044
16723
|
async function scanContent(content, opts, filePath) {
|
|
17045
|
-
|
|
16724
|
+
return scan(content, {
|
|
17046
16725
|
contextAware: true,
|
|
17047
16726
|
entropyAnalysis: opts.entropy !== false,
|
|
17048
16727
|
...filePath ? { filePath } : {},
|
|
17049
16728
|
...opts.presetName ? { presetName: opts.presetName } : {}
|
|
17050
|
-
};
|
|
17051
|
-
if (resolveScanLevel(opts) === 2) {
|
|
17052
|
-
return await scanLevel2(content, langForFile(filePath), base);
|
|
17053
|
-
}
|
|
17054
|
-
return scan(content, base);
|
|
16729
|
+
});
|
|
17055
16730
|
}
|
|
17056
16731
|
async function scanFile(filePath, opts) {
|
|
17057
16732
|
const content = readFileSync5(filePath, "utf-8");
|
|
@@ -17142,7 +16817,6 @@ function resolveFormat(opts, defaultSarif = false) {
|
|
|
17142
16817
|
return "text";
|
|
17143
16818
|
}
|
|
17144
16819
|
async function outputMultiFileResults(label, files, opts, { defaultSarif = false, ciMode = false } = {}) {
|
|
17145
|
-
const { level, astUsed } = resolveLevelWithAst(opts);
|
|
17146
16820
|
const sourceFiles = files.filter(isSupportedFile);
|
|
17147
16821
|
if (sourceFiles.length === 0) {
|
|
17148
16822
|
const fmt3 = resolveFormat(opts, defaultSarif);
|
|
@@ -17190,7 +16864,7 @@ async function outputMultiFileResults(label, files, opts, { defaultSarif = false
|
|
|
17190
16864
|
console.log(chalk3.cyan(`
|
|
17191
16865
|
Pretense Scan \u2014 ${label}
|
|
17192
16866
|
`));
|
|
17193
|
-
console.log(chalk3.dim(` Files: ${sourceFiles.length} | Patterns: ${getPatternCount()}
|
|
16867
|
+
console.log(chalk3.dim(` Files: ${sourceFiles.length} | Patterns: ${getPatternCount()}
|
|
17194
16868
|
`));
|
|
17195
16869
|
for (const { file, result } of allResults) printFindings(file, result);
|
|
17196
16870
|
console.log(chalk3.dim(`
|
|
@@ -17199,7 +16873,7 @@ async function outputMultiFileResults(label, files, opts, { defaultSarif = false
|
|
|
17199
16873
|
process.exit(findingsExitCode);
|
|
17200
16874
|
}
|
|
17201
16875
|
function addScanOpts(cmd) {
|
|
17202
|
-
return cmd.option("--json", "Output results as JSON (alias for --format json)", false).option("--format <fmt>", "Output format: text, json, sarif, csv (default: text)").option("--severity <lvl>", "Minimum severity to report: low, medium, high, critical").option("--no-entropy", "Disable entropy-based detection", false).option(
|
|
16876
|
+
return cmd.option("--json", "Output results as JSON (alias for --format json)", false).option("--format <fmt>", "Output format: text, json, sarif, csv (default: text)").option("--severity <lvl>", "Minimum severity to report: low, medium, high, critical").option("--no-entropy", "Disable entropy-based detection", false).option(
|
|
17203
16877
|
"--policy <preset>",
|
|
17204
16878
|
`Apply a compliance preset (${COMPLIANCE_PRESET_IDS.join(", ")}); overrides scan.compliancePreset in pretense.yaml`
|
|
17205
16879
|
);
|
|
@@ -17293,7 +16967,7 @@ function pathSubcommand() {
|
|
|
17293
16967
|
});
|
|
17294
16968
|
}
|
|
17295
16969
|
function scanCommand() {
|
|
17296
|
-
const cmd = new Command3("scan").description("Scan for secrets and PII (file, directory, or git-aware modes)").argument("[file]", "File to scan (omit to read from stdin)").option("--json", "Output results as JSON (alias for --format json)", false).option("--format <fmt>", "Output format: text, json, sarif, csv (default: text)").option("--severity <lvl>", "Minimum severity to report: low, medium, high, critical").option("--no-entropy", "Disable entropy-based detection", false).option(
|
|
16970
|
+
const cmd = new Command3("scan").description("Scan for secrets and PII (file, directory, or git-aware modes)").argument("[file]", "File to scan (omit to read from stdin)").option("--json", "Output results as JSON (alias for --format json)", false).option("--format <fmt>", "Output format: text, json, sarif, csv (default: text)").option("--severity <lvl>", "Minimum severity to report: low, medium, high, critical").option("--no-entropy", "Disable entropy-based detection", false).option(
|
|
17297
16971
|
"--policy <preset>",
|
|
17298
16972
|
`Apply a compliance preset (${COMPLIANCE_PRESET_IDS.join(", ")}); overrides scan.compliancePreset in pretense.yaml`
|
|
17299
16973
|
).action(async (file, opts = {}) => {
|
|
@@ -17338,14 +17012,12 @@ function scanCommand() {
|
|
|
17338
17012
|
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
17339
17013
|
content = Buffer.concat(chunks).toString("utf-8");
|
|
17340
17014
|
}
|
|
17341
|
-
const { level, astUsed } = resolveLevelWithAst(opts);
|
|
17342
|
-
const effectiveLevel = effectiveScanLevel(level, astUsed);
|
|
17343
17015
|
const rawResult = await scanContent(content, opts, file);
|
|
17344
17016
|
const filteredMatches = filterBySeverity(rawResult.matches, opts?.severity);
|
|
17345
17017
|
const result = { ...rawResult, matches: filteredMatches, clean: filteredMatches.length === 0 };
|
|
17346
17018
|
const fmt2 = resolveFormat(opts ?? {});
|
|
17347
17019
|
if (fmt2 === "json") {
|
|
17348
|
-
console.log(JSON.stringify(
|
|
17020
|
+
console.log(JSON.stringify(result, null, 2));
|
|
17349
17021
|
process.exit(result.clean ? 0 : 1);
|
|
17350
17022
|
}
|
|
17351
17023
|
if (fmt2 === "sarif") {
|
|
@@ -17361,7 +17033,7 @@ function scanCommand() {
|
|
|
17361
17033
|
console.log(chalk3.cyan(`
|
|
17362
17034
|
Pretense Scan \u2014 ${file ?? "stdin"}
|
|
17363
17035
|
`));
|
|
17364
|
-
console.log(chalk3.dim(` Patterns: ${getPatternCount()} |
|
|
17036
|
+
console.log(chalk3.dim(` Patterns: ${getPatternCount()} | Duration: ${result.durationMs}ms
|
|
17365
17037
|
`));
|
|
17366
17038
|
if (result.clean) {
|
|
17367
17039
|
console.log(chalk3.green(" \u2713 No secrets or PII detected\n"));
|
|
@@ -17567,8 +17239,12 @@ function logsCommand() {
|
|
|
17567
17239
|
entries = store.getRecentEntries(limit);
|
|
17568
17240
|
store.close();
|
|
17569
17241
|
} catch {
|
|
17570
|
-
|
|
17571
|
-
|
|
17242
|
+
if (opts.json) {
|
|
17243
|
+
console.log("[]");
|
|
17244
|
+
return;
|
|
17245
|
+
}
|
|
17246
|
+
console.error(chalk6.dim("\n No audit data available. The audit database has not been initialized yet."));
|
|
17247
|
+
console.error(chalk6.dim(" Run " + chalk6.cyan("pretense start") + " and make some requests first.\n"));
|
|
17572
17248
|
return;
|
|
17573
17249
|
}
|
|
17574
17250
|
if (opts.json) {
|
|
@@ -18791,7 +18467,7 @@ import { Command as Command14 } from "commander";
|
|
|
18791
18467
|
import chalk13 from "chalk";
|
|
18792
18468
|
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, chmodSync as chmodSync6 } from "fs";
|
|
18793
18469
|
import { createHash as createHash3 } from "crypto";
|
|
18794
|
-
import { resolve as resolve4
|
|
18470
|
+
import { resolve as resolve4 } from "path";
|
|
18795
18471
|
|
|
18796
18472
|
// src/secret-crypto.ts
|
|
18797
18473
|
init_esm_shims();
|
|
@@ -18887,106 +18563,43 @@ var REVERSAL_MAP_VERSION = 2;
|
|
|
18887
18563
|
function sha256Hex2(s) {
|
|
18888
18564
|
return createHash3("sha256").update(s, "utf8").digest("hex");
|
|
18889
18565
|
}
|
|
18890
|
-
function
|
|
18891
|
-
switch (extname4(filePath).toLowerCase()) {
|
|
18892
|
-
case ".py":
|
|
18893
|
-
return "python";
|
|
18894
|
-
case ".go":
|
|
18895
|
-
return "go";
|
|
18896
|
-
case ".java":
|
|
18897
|
-
return "java";
|
|
18898
|
-
case ".rb":
|
|
18899
|
-
return "ruby";
|
|
18900
|
-
case ".rs":
|
|
18901
|
-
return "rust";
|
|
18902
|
-
case ".cs":
|
|
18903
|
-
return "csharp";
|
|
18904
|
-
case ".js":
|
|
18905
|
-
case ".jsx":
|
|
18906
|
-
return "javascript";
|
|
18907
|
-
case ".tsx":
|
|
18908
|
-
case ".ts":
|
|
18909
|
-
return "typescript";
|
|
18910
|
-
default:
|
|
18911
|
-
return "typescript";
|
|
18912
|
-
}
|
|
18913
|
-
}
|
|
18914
|
-
function resolveMutateLevel(opts) {
|
|
18915
|
-
if (opts.ast) return 2;
|
|
18916
|
-
const raw2 = opts.level;
|
|
18917
|
-
if (raw2 === void 0 || raw2 === "1") return 1;
|
|
18918
|
-
if (raw2 === "2") return 2;
|
|
18919
|
-
console.error(chalk13.red(`
|
|
18920
|
-
x Invalid --level: "${raw2}". Use 1 (regex) or 2 (AST/data-flow).
|
|
18921
|
-
`));
|
|
18922
|
-
process.exit(1);
|
|
18923
|
-
}
|
|
18924
|
-
function overlaps2(aOff, aLen, bOff, bLen) {
|
|
18925
|
-
return aOff < bOff + bLen && bOff < aOff + aLen;
|
|
18926
|
-
}
|
|
18927
|
-
function innerValueFinding(content, m) {
|
|
18928
|
-
if (m.end <= m.start || m.value.length === 0) return null;
|
|
18929
|
-
const raw2 = content.slice(m.start, m.end);
|
|
18930
|
-
const idx = raw2.indexOf(m.value);
|
|
18931
|
-
if (idx < 0) return null;
|
|
18932
|
-
return { value: m.value, offset: m.start + idx, length: m.value.length, type: m.type };
|
|
18933
|
-
}
|
|
18934
|
-
async function collectMutationFindings(content, file, level) {
|
|
18566
|
+
async function collectMutationFindings(content, file) {
|
|
18935
18567
|
const l1 = scan(content, { contextAware: true, entropyAnalysis: true, filePath: file });
|
|
18936
|
-
|
|
18568
|
+
return l1.matches.map((m) => ({
|
|
18937
18569
|
value: m.value,
|
|
18938
18570
|
offset: m.start,
|
|
18939
18571
|
length: m.end - m.start,
|
|
18940
18572
|
type: m.type
|
|
18941
18573
|
}));
|
|
18942
|
-
if (level === 2) {
|
|
18943
|
-
if (!isAstCoreAvailable()) {
|
|
18944
|
-
console.error(
|
|
18945
|
-
chalk13.yellow(" ! AST core (@pretense/scanner-rs) unavailable \u2014 mutating with L1 (regex).")
|
|
18946
|
-
);
|
|
18947
|
-
}
|
|
18948
|
-
const l2 = await scanLevel2(content, langForFile2(file), {
|
|
18949
|
-
contextAware: true,
|
|
18950
|
-
entropyAnalysis: true,
|
|
18951
|
-
filePath: file
|
|
18952
|
-
});
|
|
18953
|
-
for (const m of l2.matches) {
|
|
18954
|
-
if (m.type !== "dataflow-credential") continue;
|
|
18955
|
-
const f = innerValueFinding(content, m);
|
|
18956
|
-
if (!f) continue;
|
|
18957
|
-
if (findings.some((e) => overlaps2(f.offset, f.length, e.offset, e.length))) continue;
|
|
18958
|
-
findings.push(f);
|
|
18959
|
-
}
|
|
18960
|
-
}
|
|
18961
|
-
return findings;
|
|
18962
18574
|
}
|
|
18963
18575
|
async function runMutate(file, opts = {}) {
|
|
18964
|
-
|
|
18965
|
-
let content;
|
|
18576
|
+
let raw2;
|
|
18966
18577
|
try {
|
|
18967
|
-
|
|
18578
|
+
raw2 = readFileSync14(file);
|
|
18968
18579
|
} catch {
|
|
18969
18580
|
console.error(chalk13.red(`
|
|
18970
18581
|
x Cannot read file: ${file}
|
|
18971
18582
|
`));
|
|
18972
18583
|
return 1;
|
|
18973
18584
|
}
|
|
18974
|
-
const
|
|
18585
|
+
const content = raw2.toString("utf-8");
|
|
18586
|
+
if (!Buffer.from(content, "utf-8").equals(raw2)) {
|
|
18587
|
+
console.error(
|
|
18588
|
+
chalk13.red(`
|
|
18589
|
+
x Not valid UTF-8: ${file}`) + chalk13.dim(`
|
|
18590
|
+
Mutating would replace the undecodable bytes with U+FFFD and the`) + chalk13.dim(`
|
|
18591
|
+
original content could not be restored. File left untouched.
|
|
18592
|
+
`)
|
|
18593
|
+
);
|
|
18594
|
+
return 1;
|
|
18595
|
+
}
|
|
18596
|
+
const findings = await collectMutationFindings(content, file);
|
|
18975
18597
|
if (findings.length === 0) {
|
|
18976
18598
|
console.error(chalk13.dim(` No secrets found in ${file} \u2014 nothing to mutate.`));
|
|
18977
18599
|
if (!opts.inPlace && !opts.output) process.stdout.write(content);
|
|
18978
18600
|
return 0;
|
|
18979
18601
|
}
|
|
18980
18602
|
const result = mutateSecrets(content, findings);
|
|
18981
|
-
if (opts.inPlace) {
|
|
18982
|
-
writeFileSync9(file, result.content);
|
|
18983
|
-
console.error(chalk13.green(` \u2713 Mutated ${result.mutations.length} secrets in ${file} (in-place)`));
|
|
18984
|
-
} else if (opts.output) {
|
|
18985
|
-
writeFileSync9(opts.output, result.content);
|
|
18986
|
-
console.error(chalk13.green(` \u2713 Mutated ${result.mutations.length} secrets \u2192 ${opts.output}`));
|
|
18987
|
-
} else {
|
|
18988
|
-
process.stdout.write(result.content);
|
|
18989
|
-
}
|
|
18990
18603
|
if (opts.map) {
|
|
18991
18604
|
const absFile = resolve4(file);
|
|
18992
18605
|
const projectKey = getOrCreateProjectKey(findProjectRoot(absFile), opts.keysDir);
|
|
@@ -19001,7 +18614,18 @@ async function runMutate(file, opts = {}) {
|
|
|
19001
18614
|
type: m.type
|
|
19002
18615
|
}))
|
|
19003
18616
|
};
|
|
19004
|
-
|
|
18617
|
+
try {
|
|
18618
|
+
writeFileSync9(opts.map, JSON.stringify(mapFile, null, 2), { mode: 384 });
|
|
18619
|
+
} catch (e) {
|
|
18620
|
+
console.error(
|
|
18621
|
+
chalk13.red(`
|
|
18622
|
+
x Cannot write reversal map: ${opts.map}`) + chalk13.dim(`
|
|
18623
|
+
${e.message}`) + chalk13.dim(`
|
|
18624
|
+
Nothing was mutated \u2014 without a map the original could not be restored.
|
|
18625
|
+
`)
|
|
18626
|
+
);
|
|
18627
|
+
return 1;
|
|
18628
|
+
}
|
|
19005
18629
|
try {
|
|
19006
18630
|
chmodSync6(opts.map, 384);
|
|
19007
18631
|
} catch {
|
|
@@ -19010,13 +18634,32 @@ async function runMutate(file, opts = {}) {
|
|
|
19010
18634
|
chalk13.green(` \u2713 Wrote encrypted reversal map \u2192 ${opts.map}`) + chalk13.dim(" (AES-256-GCM, mode 0600)")
|
|
19011
18635
|
);
|
|
19012
18636
|
}
|
|
18637
|
+
try {
|
|
18638
|
+
if (opts.inPlace) {
|
|
18639
|
+
writeFileSync9(file, result.content);
|
|
18640
|
+
console.error(chalk13.green(` \u2713 Mutated ${result.mutations.length} secrets in ${file} (in-place)`));
|
|
18641
|
+
} else if (opts.output) {
|
|
18642
|
+
writeFileSync9(opts.output, result.content);
|
|
18643
|
+
console.error(chalk13.green(` \u2713 Mutated ${result.mutations.length} secrets \u2192 ${opts.output}`));
|
|
18644
|
+
} else {
|
|
18645
|
+
process.stdout.write(result.content);
|
|
18646
|
+
}
|
|
18647
|
+
} catch (e) {
|
|
18648
|
+
console.error(
|
|
18649
|
+
chalk13.red(`
|
|
18650
|
+
x Cannot write mutated content: ${opts.output ?? file}`) + chalk13.dim(`
|
|
18651
|
+
${e.message}
|
|
18652
|
+
`)
|
|
18653
|
+
);
|
|
18654
|
+
return 1;
|
|
18655
|
+
}
|
|
19013
18656
|
if (opts.showMap) {
|
|
19014
18657
|
console.error(JSON.stringify(result.mutations, null, 2));
|
|
19015
18658
|
}
|
|
19016
18659
|
return 0;
|
|
19017
18660
|
}
|
|
19018
18661
|
function mutateCommand() {
|
|
19019
|
-
return new Command14("mutate").description("Mutate secrets in a file to deterministic synthetics").argument("<file>", "File to mutate").option("-i, --in-place", "Write back to the input file").option("-o, --output <path>", "Write mutated content to a specific file").option("--map <path>", "Write the encrypted reversal map (for `pretense reverse`) to a file").option("--
|
|
18662
|
+
return new Command14("mutate").description("Mutate secrets in a file to deterministic synthetics").argument("<file>", "File to mutate").option("-i, --in-place", "Write back to the input file").option("-o, --output <path>", "Write mutated content to a specific file").option("--map <path>", "Write the encrypted reversal map (for `pretense reverse`) to a file").option("--show-map", "Print mutation map JSON to stderr").action(async (file, opts) => {
|
|
19020
18663
|
const code = await runMutate(file, opts);
|
|
19021
18664
|
process.exit(code);
|
|
19022
18665
|
});
|
|
@@ -19527,7 +19170,7 @@ function findClosestCommand(input, knownCommands) {
|
|
|
19527
19170
|
return bestDist <= 3 ? best : null;
|
|
19528
19171
|
}
|
|
19529
19172
|
var program = new Command20();
|
|
19530
|
-
program.name("pretense").description(chalk19.bold("AI firewall") + " \u2014 mutates proprietary code before LLM API calls").version("0.6.
|
|
19173
|
+
program.name("pretense").description(chalk19.bold("AI firewall") + " \u2014 mutates proprietary code before LLM API calls").version("0.6.5", "-v, --version").addHelpText("after", `
|
|
19531
19174
|
${chalk19.bold("Quick start:")}
|
|
19532
19175
|
${chalk19.cyan("pretense scan")} ${chalk19.dim("<file|dir>")} Scan for secrets and PII
|
|
19533
19176
|
${chalk19.cyan("pretense mutate")} ${chalk19.dim("<file>")} Preview code mutations
|
package/dist/postinstall.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pretense/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "Local-first AI firewall that mutates proprietary code before sending to LLM APIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,14 +11,6 @@
|
|
|
11
11
|
"README.md",
|
|
12
12
|
"LICENSE"
|
|
13
13
|
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build": "tsup",
|
|
16
|
-
"dev": "tsx src/index.ts",
|
|
17
|
-
"prepublishOnly": "pnpm build",
|
|
18
|
-
"postinstall": "node -e \"fs.existsSync('dist/postinstall.js') && import('./dist/postinstall.js')\" || true",
|
|
19
|
-
"test": "vitest run",
|
|
20
|
-
"lint": "tsc --noEmit"
|
|
21
|
-
},
|
|
22
14
|
"dependencies": {
|
|
23
15
|
"better-sqlite3": "^11.0.0",
|
|
24
16
|
"chalk": "^5.3.0",
|
|
@@ -26,19 +18,19 @@
|
|
|
26
18
|
"yaml": "^2.4.0"
|
|
27
19
|
},
|
|
28
20
|
"devDependencies": {
|
|
29
|
-
"@pretense/billing": "workspace:*",
|
|
30
|
-
"@pretense/compliance-engine": "workspace:*",
|
|
31
|
-
"@pretense/protocol": "workspace:*",
|
|
32
|
-
"@pretense/learner": "workspace:*",
|
|
33
|
-
"@pretense/mutator": "workspace:*",
|
|
34
|
-
"@pretense/proxy": "workspace:*",
|
|
35
|
-
"@pretense/scanner": "workspace:*",
|
|
36
|
-
"@pretense/store": "workspace:*",
|
|
37
21
|
"@types/node": "^20.0.0",
|
|
38
22
|
"tsup": "^8.0.0",
|
|
39
23
|
"tsx": "^4.0.0",
|
|
40
24
|
"typescript": "^5.4.0",
|
|
41
|
-
"vitest": "^1.0.0"
|
|
25
|
+
"vitest": "^1.0.0",
|
|
26
|
+
"@pretense/protocol": "0.1.0",
|
|
27
|
+
"@pretense/learner": "0.2.0",
|
|
28
|
+
"@pretense/mutator": "0.2.0",
|
|
29
|
+
"@pretense/scanner": "0.2.0",
|
|
30
|
+
"@pretense/store": "0.2.0",
|
|
31
|
+
"@pretense/proxy": "0.1.0",
|
|
32
|
+
"@pretense/compliance-engine": "0.1.0",
|
|
33
|
+
"@pretense/billing": "0.1.0"
|
|
42
34
|
},
|
|
43
35
|
"publishConfig": {
|
|
44
36
|
"access": "public",
|
|
@@ -78,5 +70,12 @@
|
|
|
78
70
|
},
|
|
79
71
|
"engines": {
|
|
80
72
|
"node": ">=20.0.0"
|
|
73
|
+
},
|
|
74
|
+
"scripts": {
|
|
75
|
+
"build": "tsup",
|
|
76
|
+
"dev": "tsx src/index.ts",
|
|
77
|
+
"postinstall": "node -e \"fs.existsSync('dist/postinstall.js') && import('./dist/postinstall.js')\" || true",
|
|
78
|
+
"test": "vitest run",
|
|
79
|
+
"lint": "tsc --noEmit"
|
|
81
80
|
}
|
|
82
|
-
}
|
|
81
|
+
}
|