@methiu/raigal 0.2.3 → 0.2.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.
@@ -1,4 +1,4 @@
1
- import { t as APP_VERSION } from "./version-B4eYJn3o.js";
1
+ import { t as APP_VERSION } from "./version-BlgPglaO.js";
2
2
  import { i as ENGINE_INFO, n as withFindingAssessments, t as summarizeFindingAssessments } from "./finding-assessment-CGpt5YUR.js";
3
3
  //#region src/output/json.ts
4
4
  const buildJsonOutput = (results, scoreResult, fileCount, elapsedMs, coverage) => {
package/dist/mcp.js CHANGED
@@ -84,7 +84,7 @@ const getActiveToken = () => {
84
84
  };
85
85
  //#endregion
86
86
  //#region src/version.ts
87
- const APP_VERSION = "0.2.3";
87
+ const APP_VERSION = "0.2.5";
88
88
  //#endregion
89
89
  //#region src/cloud/contract.ts
90
90
  const Severity = z.enum(["error", "warning"]);
@@ -347,9 +347,7 @@ const verifyEntitlementJwt = (jwt, options = {}) => {
347
347
  if (!header.kid) throw new JwtVerificationError("JWT header missing 'kid'", "unknown_kid");
348
348
  const publicKey = getPublicKey(header.kid);
349
349
  if (!publicKey) throw new JwtVerificationError(`Unknown or untrusted signing key id (kid: ${header.kid})`, "unknown_kid");
350
- const signedData = Buffer.from(`${headerB64}.${payloadB64}`, "utf-8");
351
- const signature = Buffer.from(signatureB64, "base64url");
352
- if (!verify(null, signedData, publicKey, signature)) throw new JwtVerificationError("Invalid JWT cryptographic signature", "invalid_signature");
350
+ if (!verify(null, Buffer.from(`${headerB64}.${payloadB64}`, "utf-8"), publicKey, Buffer.from(signatureB64, "base64url"))) throw new JwtVerificationError("Invalid JWT cryptographic signature", "invalid_signature");
353
351
  let rawPayload;
354
352
  try {
355
353
  rawPayload = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf-8"));
@@ -361,7 +359,7 @@ const verifyEntitlementJwt = (jwt, options = {}) => {
361
359
  const claims = parsed.data;
362
360
  const expectedIssuer = process.env.RAIGAL_ISSUER?.trim() || "https://app.raigal.dev";
363
361
  if (claims.iss !== expectedIssuer) throw new JwtVerificationError(`Untrusted issuer: ${claims.iss}`, "invalid_issuer");
364
- if (!isVersionAtLeast("0.2.3", claims.min_cli_version)) throw new JwtVerificationError(`CLI version ${APP_VERSION} is below required minimum ${claims.min_cli_version}. Run "raigal update" or "npm install -g @methiu/raigal@latest".`, "cli_version_unsupported");
362
+ if (!isVersionAtLeast("0.2.5", claims.min_cli_version)) throw new JwtVerificationError(`CLI version ${APP_VERSION} is below required minimum ${claims.min_cli_version}. Run "raigal update" or "npm install -g @methiu/raigal@latest".`, "cli_version_unsupported");
365
363
  const now = options.nowSeconds ?? Math.floor(Date.now() / 1e3);
366
364
  const grace = options.allowGraceSeconds ?? 0;
367
365
  if (now > claims.exp + grace) {
@@ -395,7 +393,7 @@ const fetchGitHubOidcToken = async () => {
395
393
  };
396
394
  //#endregion
397
395
  //#region src/cloud/entitlement.ts
398
- const GRACE_PERIOD_SECONDS = 259200;
396
+ const GRACE_PERIOD_SECONDS = 4320 * 60;
399
397
  var MissingCredentialError = class extends Error {
400
398
  constructor(message = "No organization credential found") {
401
399
  super(message);
@@ -520,8 +518,7 @@ const getEntitlement = async () => {
520
518
  }
521
519
  } else oidcToken = await fetchGitHubOidcToken();
522
520
  try {
523
- const tokenToPass = activeToken?.token ?? "";
524
- const response = await fetchEntitlementFromApi(tokenToPass, oidcToken);
521
+ const response = await fetchEntitlementFromApi(activeToken?.token ?? "", oidcToken);
525
522
  const claims = verifyEntitlementJwt(response.entitlement, { nowSeconds: now });
526
523
  saveCachedEntitlement(response.entitlement, response.refresh_after);
527
524
  return {
@@ -816,7 +813,7 @@ const DEFAULT_CONFIG = {
816
813
  //#endregion
817
814
  //#region src/config/extends.ts
818
815
  const MAX_DEPTH$1 = 5;
819
- const MAX_CONFIG_BYTES = 1048576;
816
+ const MAX_CONFIG_BYTES = 1024 * 1024;
820
817
  const isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
821
818
  const deepMerge = (...sources) => {
822
819
  const result = {};
@@ -1292,8 +1289,7 @@ const loadConfig = (directory) => {
1292
1289
  const configPath = findConfigFile(directory);
1293
1290
  if (!configPath) return DEFAULT_CONFIG;
1294
1291
  try {
1295
- const merged = loadConfigChain(configPath);
1296
- return validateConfig(merged, configPath);
1292
+ return validateConfig(loadConfigChain(configPath), configPath);
1297
1293
  } catch (error) {
1298
1294
  if (error instanceof ConfigError) throw error;
1299
1295
  throw new ConfigError(configPath, `Failed to parse ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
@@ -1471,7 +1467,7 @@ const filterExcludedDiagnostics = (diagnostics, rootDirectory, excludePatterns)
1471
1467
  };
1472
1468
  //#endregion
1473
1469
  //#region src/utils/project-path-safety.ts
1474
- const MAX_PROJECT_CONFIG_BYTES = 1048576;
1470
+ const MAX_PROJECT_CONFIG_BYTES = 1024 * 1024;
1475
1471
  const isWithinDirectory$2 = (rootDirectory, candidate) => {
1476
1472
  const relative = path.relative(rootDirectory, candidate);
1477
1473
  return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
@@ -1558,7 +1554,7 @@ const isAutoGenerated = (filePath) => {
1558
1554
  };
1559
1555
  //#endregion
1560
1556
  //#region src/utils/git-ignore.ts
1561
- const MAX_BUFFER$1 = 52428800;
1557
+ const MAX_BUFFER$1 = 50 * 1024 * 1024;
1562
1558
  const NOT_IGNORED_ARGUMENTS = [
1563
1559
  "ls-files",
1564
1560
  "--cached",
@@ -1669,7 +1665,7 @@ const dropGitIgnoredPaths = (rootDirectory, absolutePaths) => {
1669
1665
  };
1670
1666
  //#endregion
1671
1667
  //#region src/utils/project-file-list.ts
1672
- const MAX_BUFFER = 52428800;
1668
+ const MAX_BUFFER = 50 * 1024 * 1024;
1673
1669
  const normalizePruneDirectories = (directories) => new Set([...directories].map((directory) => directory.toLowerCase()));
1674
1670
  const isInPrunedDirectory = (filePath, pruneDirectories) => {
1675
1671
  const pathSegments = filePath.split("/");
@@ -6032,8 +6028,7 @@ const isJsRelativeOrAbsolute = (spec) => spec.startsWith(".") || spec.startsWith
6032
6028
  const RUNTIME_BUILTINS = /* @__PURE__ */ new Set(["bun"]);
6033
6029
  const isJsBuiltin = (spec) => {
6034
6030
  if (RUNTIME_BUILTINS.has(spec)) return true;
6035
- const stripped = spec.startsWith("node:") ? spec.slice(5) : spec;
6036
- return isBuiltin(stripped) || isBuiltin(spec);
6031
+ return isBuiltin(spec.startsWith("node:") ? spec.slice(5) : spec) || isBuiltin(spec);
6037
6032
  };
6038
6033
  const VIRTUAL_MODULE_PREFIXES = [
6039
6034
  "astro:",
@@ -6245,8 +6240,7 @@ const isLocalAliasReplacement = (rawValue, configDirectory, rootDirectory) => {
6245
6240
  if (!target) return false;
6246
6241
  if (!target.startsWith(".") && !target.startsWith("/") && !target.startsWith("~/") && !target.startsWith("@/")) return false;
6247
6242
  const normalized = target.startsWith("~/") || target.startsWith("@/") ? target.slice(2) : target;
6248
- const candidate = path.isAbsolute(normalized) ? normalized : path.resolve(configDirectory, normalized);
6249
- return isRootBoundedTarget(candidate, rootDirectory);
6243
+ return isRootBoundedTarget(path.isAbsolute(normalized) ? normalized : path.resolve(configDirectory, normalized), rootDirectory);
6250
6244
  };
6251
6245
  const hasValidPackageImportTarget = (value, packageDirectory, rootDirectory) => {
6252
6246
  if (!isRootBoundedTarget(packageDirectory, rootDirectory)) return false;
@@ -7366,9 +7360,7 @@ const isRustDocCommentLine = (line) => {
7366
7360
  };
7367
7361
  const collectBlocks = (sourceLines, syntax, content, ext) => {
7368
7362
  const blocks = [];
7369
- const actualContent = content ?? sourceLines.join("\n");
7370
- const actualExt = ext ?? (syntax.linePrefixes.includes("//") ? ".ts" : ".py");
7371
- const commentLines = getCommentLines(actualContent, actualExt);
7363
+ const commentLines = getCommentLines(content ?? sourceLines.join("\n"), ext ?? (syntax.linePrefixes.includes("//") ? ".ts" : ".py"));
7372
7364
  let i = 0;
7373
7365
  while (i < sourceLines.length) {
7374
7366
  const line = sourceLines[i];
@@ -7696,8 +7688,7 @@ const detectNarrativeComments = async (context) => {
7696
7688
  } catch {
7697
7689
  continue;
7698
7690
  }
7699
- const lines = content.split("\n");
7700
- const blocks = collectBlocks(lines, syntax, content, ext);
7691
+ const blocks = collectBlocks(content.split("\n"), syntax, content, ext);
7701
7692
  for (const block of blocks) {
7702
7693
  const { matched, reason } = detectNarrativeInBlock(block, ext);
7703
7694
  if (!matched) continue;
@@ -9649,8 +9640,7 @@ const checkFunctionDiagnostics = (relativePath, fn, limits, ext) => {
9649
9640
  const results = [];
9650
9641
  const multiplier = functionLocMultiplier(fn, ext);
9651
9642
  const fnMax = functionLocBudget(fn, ext, limits.maxFunctionLoc);
9652
- const effectiveLineCount = fn.lineCount - fn.templateLines;
9653
- if (exceedsLimit(effectiveLineCount, limits.maxFunctionLoc, multiplier)) results.push({
9643
+ if (exceedsLimit(fn.lineCount - fn.templateLines, limits.maxFunctionLoc, multiplier)) results.push({
9654
9644
  filePath: relativePath,
9655
9645
  engine: "code-quality",
9656
9646
  rule: "complexity/function-too-long",
@@ -9747,7 +9737,7 @@ const isLowSignalMarkupWindow = (lines) => {
9747
9737
  return lines.filter((line) => SVG_MARKUP_RE.test(line)).length >= Math.ceil(WINDOW_SIZE / 2);
9748
9738
  };
9749
9739
  const isLowSignalDataWindow = (lines) => {
9750
- return lines.filter((line) => DATA_LITERAL_RE.test(line)).length >= 9;
9740
+ return lines.filter((line) => DATA_LITERAL_RE.test(line)).length >= WINDOW_SIZE - 1;
9751
9741
  };
9752
9742
  const findSuppressedLines = (lines) => {
9753
9743
  const suppressed = /* @__PURE__ */ new Set();
@@ -9779,7 +9769,7 @@ const collectMeaningfulLines = (content) => {
9779
9769
  if (isLowSignalDataWindow(window)) continue;
9780
9770
  if (window.every(isTrivialLine)) continue;
9781
9771
  const normalised = window.map(normaliseLine);
9782
- if (normalised.filter((n) => n.length > 0 && n !== "}" && n !== "{").length < 9) continue;
9772
+ if (normalised.filter((n) => n.length > 0 && n !== "}" && n !== "{").length < WINDOW_SIZE - 1) continue;
9783
9773
  if (new Set(normalised).size < MIN_DISTINCT_LINES) continue;
9784
9774
  hits.push({
9785
9775
  startLine: i + 1,
@@ -10652,7 +10642,7 @@ const runClangFormat = async (context) => {
10652
10642
  };
10653
10643
  //#endregion
10654
10644
  //#region src/engines/format/dotnet-format.ts
10655
- const REPORT_FILENAME = ".aislop-dotnet-format.json";
10645
+ const REPORT_FILENAME = ".raigal-dotnet-format.json";
10656
10646
  const parseDotnetFormatReport = (json, rootDirectory) => {
10657
10647
  if (!json) return [];
10658
10648
  let report;
@@ -11114,8 +11104,7 @@ const parseClangTidyOutput = (output, rootDirectory) => {
11114
11104
  const runClangTidy = async (context) => {
11115
11105
  const compileCommandsDir = findCompileCommandsDir(context);
11116
11106
  if (!compileCommandsDir) return [];
11117
- const implSources = findCppSources(context).filter((f) => CPP_IMPL_EXTENSIONS.has(path.extname(f).toLowerCase()));
11118
- const sources = filterSourcesInDatabase(implSources, readCompileCommandsFiles(compileCommandsDir));
11107
+ const sources = filterSourcesInDatabase(findCppSources(context).filter((f) => CPP_IMPL_EXTENSIONS.has(path.extname(f).toLowerCase())), readCompileCommandsFiles(compileCommandsDir));
11119
11108
  if (sources.length === 0) return [];
11120
11109
  const diagnostics = [];
11121
11110
  for (const chunk of chunkFilePaths(sources, CLANG_TIDY_CHUNK_MAX_FILES)) try {
@@ -12449,8 +12438,7 @@ const resolveTrustedTscPath = () => {
12449
12438
  };
12450
12439
  const isReferenceOnlyConfig = (tsconfigPath) => {
12451
12440
  try {
12452
- const raw = fs.readFileSync(tsconfigPath, "utf-8");
12453
- const parsed = parseJsonc(raw);
12441
+ const parsed = parseJsonc(fs.readFileSync(tsconfigPath, "utf-8"));
12454
12442
  if (!parsed) return false;
12455
12443
  return Array.isArray(parsed.references) && !parsed.files && !parsed.include && !parsed.extends;
12456
12444
  } catch {
@@ -13317,11 +13305,10 @@ const auditSkippedDiagnostic = (source, help) => ({
13317
13305
  });
13318
13306
  const runNpmAudit = async (rootDir, timeout) => {
13319
13307
  try {
13320
- const result = await runSubprocess("npm", ["audit", "--json"], {
13308
+ return parseJsAudit((await runSubprocess("npm", ["audit", "--json"], {
13321
13309
  cwd: rootDir,
13322
13310
  timeout
13323
- });
13324
- return parseJsAudit(result.stdout, "npm audit", readRuntimeDependencies(rootDir));
13311
+ })).stdout, "npm audit", readRuntimeDependencies(rootDir));
13325
13312
  } catch (error) {
13326
13313
  return [auditSkippedDiagnostic("npm audit", `Failed to run npm audit: ${errorMessageOf(error)}`)];
13327
13314
  }
@@ -13342,11 +13329,10 @@ const runBunAudit = async (rootDir, timeout) => {
13342
13329
  const runPnpmAuditWithFallback = async (rootDir, timeout) => {
13343
13330
  const canFallbackToNpm = fs.existsSync(path.join(rootDir, "package-lock.json"));
13344
13331
  try {
13345
- const result = await runSubprocess("pnpm", ["audit", "--json"], {
13332
+ const diagnostics = parseJsAudit((await runSubprocess("pnpm", ["audit", "--json"], {
13346
13333
  cwd: rootDir,
13347
13334
  timeout
13348
- });
13349
- const diagnostics = parseJsAudit(result.stdout, "pnpm audit", readRuntimeDependencies(rootDir));
13335
+ })).stdout, "pnpm audit", readRuntimeDependencies(rootDir));
13350
13336
  if (diagnostics.some((d) => d.rule === "security/dependency-audit-skipped")) {
13351
13337
  if (canFallbackToNpm) return runNpmAudit(rootDir, timeout);
13352
13338
  return diagnostics;
@@ -14153,10 +14139,7 @@ const runEngines = async (context, enabledEngines, onStart, onComplete) => {
14153
14139
  failed: true,
14154
14140
  skipReason: r.reason instanceof Error ? r.reason.message : String(r.reason)
14155
14141
  });
14156
- const stripped = stripSecretDiagnostics(finalResults);
14157
- const csharp = dedupeCSharpAsync(stripped);
14158
- const comments = dedupeOverlappingComments(csharp);
14159
- return dedupeEquivalenceDiagnostics(comments);
14142
+ return dedupeEquivalenceDiagnostics(dedupeOverlappingComments(dedupeCSharpAsync(stripSecretDiagnostics(finalResults))));
14160
14143
  };
14161
14144
  const stripSecretDiagnostics = (results) => {
14162
14145
  for (const result of results) for (const d of result.diagnostics) if (d.redactSource || isSecretClassRule(d.rule)) {
@@ -14381,8 +14364,7 @@ const calculateScore = (diagnostics, weights, thresholds, sourceFileCount, smoot
14381
14364
  const capScale = Math.max(1, fileCount.effectiveSourceFileCount / CAP_REFERENCE_FILES);
14382
14365
  const defaultRuleCap = typeof maxPerRule === "number" && maxPerRule > 0 ? maxPerRule : null;
14383
14366
  const capForRule = (key) => {
14384
- const rule = key.slice(key.indexOf(":") + 1);
14385
- const ruleCap = scoreImpactForRule(rule).cap;
14367
+ const ruleCap = scoreImpactForRule(key.slice(key.indexOf(":") + 1)).cap;
14386
14368
  if (typeof ruleCap === "number") return defaultRuleCap ? Math.min(defaultRuleCap, ruleCap) : ruleCap;
14387
14369
  return defaultRuleCap;
14388
14370
  };
@@ -14495,10 +14477,8 @@ const detectSourceLanguages = (sourceFiles) => {
14495
14477
  const detectLanguages = (directory, sourceFiles) => {
14496
14478
  const languages = new Set(detectSourceLanguages(sourceFiles));
14497
14479
  for (const [file, lang] of Object.entries(LANGUAGE_SIGNALS)) if (fs.existsSync(path.join(directory, file))) languages.add(lang);
14498
- if (readPackageJson(path.join(directory, "package.json"))) {
14499
- if (fs.existsSync(path.join(directory, "tsconfig.json"))) languages.add("typescript");
14500
- else languages.add("javascript");
14501
- }
14480
+ if (readPackageJson(path.join(directory, "package.json"))) if (fs.existsSync(path.join(directory, "tsconfig.json"))) languages.add("typescript");
14481
+ else languages.add("javascript");
14502
14482
  for (const signal of PYTHON_SIGNALS) if (fs.existsSync(path.join(directory, signal))) {
14503
14483
  languages.add("python");
14504
14484
  break;
@@ -14694,7 +14674,9 @@ const baselinePath = (cwd) => {
14694
14674
  if (fs.existsSync(raigalCandidate)) return raigalCandidate;
14695
14675
  const raigalDir = path.join(cwd, ".raigal");
14696
14676
  if (fs.existsSync(raigalDir)) return raigalCandidate;
14697
- return path.join(cwd, ".aislop", "baseline.json");
14677
+ const legacyCandidate = path.join(cwd, ".aislop", "baseline.json");
14678
+ if (fs.existsSync(legacyCandidate)) return legacyCandidate;
14679
+ return raigalCandidate;
14698
14680
  };
14699
14681
  const readBaseline = (cwd) => {
14700
14682
  const raw = readIfExists(baselinePath(cwd));
@@ -14705,7 +14687,7 @@ const readBaseline = (cwd) => {
14705
14687
  const findingFingerprints = parsed.findingFingerprints ?? [];
14706
14688
  const needsWindowsMigration = parsed.pathFormat !== "posix";
14707
14689
  return {
14708
- schema: "aislop.baseline.v2",
14690
+ schema: "raigal.baseline.v2",
14709
14691
  pathFormat: "posix",
14710
14692
  updatedAt: parsed.updatedAt ?? "",
14711
14693
  score: parsed.score ?? 0,
@@ -14886,9 +14868,7 @@ const summariseDiagnostics = (diagnostics, rootDirectory) => {
14886
14868
  const runScan = async (cwd) => {
14887
14869
  const project = await discoverProject(cwd);
14888
14870
  const config = loadConfig(cwd);
14889
- const context = buildEngineContext(project.rootDirectory, project, config);
14890
- const enabled = enabledEnginesFromConfig(config);
14891
- const diagnostics = (await runEngines(context, enabled)).flatMap((r) => r.diagnostics);
14871
+ const diagnostics = (await runEngines(buildEngineContext(project.rootDirectory, project, config), enabledEnginesFromConfig(config))).flatMap((r) => r.diagnostics);
14892
14872
  const { score } = calculateScore(diagnostics, config.scoring.weights, config.scoring.thresholds, project.sourceFileCount, config.scoring.smoothing, config.scoring.maxPerRule);
14893
14873
  const errorCount = diagnostics.filter((d) => d.severity === "error").length;
14894
14874
  const failBelow = config.ci.failBelow;
@@ -15268,11 +15248,10 @@ const track = (input) => {
15268
15248
  cachedInstallId = ensured.installId;
15269
15249
  installCreated = ensured.created;
15270
15250
  }
15271
- const merged = {
15251
+ const { clean, dropped } = redactProperties({
15272
15252
  ...baseProperties(cachedInstallId),
15273
15253
  ...input.properties
15274
- };
15275
- const { clean, dropped } = redactProperties(merged);
15254
+ });
15276
15255
  if (isDebug()) {
15277
15256
  const compact = JSON.stringify({
15278
15257
  event: input.event,
@@ -4,7 +4,7 @@ const mountAgentTui = async (store) => {
4
4
  const [{ render }, React, { AgentApp }] = await Promise.all([
5
5
  import("ink"),
6
6
  import("react"),
7
- import("./AgentApp-DJYdD1VH.js")
7
+ import("./AgentApp-CIiRfOun.js")
8
8
  ]);
9
9
  process.stdout.write("\x1B[?1049h\x1B[?25l");
10
10
  const instance = render(React.createElement(AgentApp, { store }), { exitOnCtrlC: false });
@@ -1,4 +1,4 @@
1
- import { t as APP_VERSION } from "./version-B4eYJn3o.js";
1
+ import { t as APP_VERSION } from "./version-BlgPglaO.js";
2
2
  import { n as isSecretClassRule, t as FIXED_SECRET_DIAGNOSTIC_MESSAGE } from "./mask-secrets-BXn-ZSEh.js";
3
3
  import path from "node:path";
4
4
  //#region src/output/sarif.ts
@@ -1,6 +1,6 @@
1
1
  import "node:fs";
2
2
  import "node:url";
3
3
  //#region src/version.ts
4
- const APP_VERSION = "0.2.3";
4
+ const APP_VERSION = "0.2.5";
5
5
  //#endregion
6
6
  export { APP_VERSION as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@methiu/raigal",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },