calllint 1.5.1 → 1.7.0

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.
Files changed (2) hide show
  1. package/dist/index.js +222 -222
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -895,6 +895,228 @@ function resolveArtifactIdentity(input) {
895
895
  return identity;
896
896
  }
897
897
 
898
+ // ../../packages/evidence/src/types.ts
899
+ var EVIDENCE_SCHEMA_VERSION = "calllint.evidence-provider.v0";
900
+
901
+ // ../../packages/evidence/src/providers/skillspector.ts
902
+ function pinnedVersion(raw) {
903
+ const tool = raw.tool;
904
+ const commit = typeof raw.commit === "string" && raw.commit || tool && typeof tool.commit === "string" && tool.commit || "";
905
+ if (commit) return `git:${commit}`;
906
+ const version = typeof raw.version === "string" && raw.version || tool && typeof tool.version === "string" && tool.version || "";
907
+ return version || void 0;
908
+ }
909
+ function parseSkillSpectorJson(parsed) {
910
+ const raw = asObject(parsed, "SkillSpector JSON root");
911
+ const degradedReasons = [];
912
+ const usedLlm = raw.llm_used === true || raw.llmUsed === true;
913
+ const scanMode = usedLlm ? "llm" : "static";
914
+ const rawFindings = arrayOf(raw.findings) ?? arrayOf(raw.results) ?? [];
915
+ const findings = rawFindings.map((f) => {
916
+ const o = asObject(f, "SkillSpector finding");
917
+ return {
918
+ providerRuleId: String(o.rule_id ?? o.ruleId ?? o.id ?? "unknown"),
919
+ providerSeverity: String(o.severity ?? o.level ?? "unknown"),
920
+ message: typeof o.message === "string" ? o.message : void 0,
921
+ locations: extractLocations(o)
922
+ };
923
+ });
924
+ let completenessHint;
925
+ const status = String(raw.status ?? raw.scan_status ?? "").toLowerCase();
926
+ if (status && status !== "complete" && status !== "completed" && status !== "success") {
927
+ degradedReasons.push(`SkillSpector reported status "${status}"`);
928
+ completenessHint = status === "partial" ? "partial" : "degraded";
929
+ }
930
+ if (raw.partial === true) {
931
+ degradedReasons.push("SkillSpector reported a partial scan");
932
+ completenessHint = completenessHint ?? "partial";
933
+ }
934
+ if (raw.degraded === true) {
935
+ degradedReasons.push("SkillSpector reported a degraded scan");
936
+ completenessHint = "degraded";
937
+ }
938
+ const coverage = (arrayOf(raw.categories) ?? arrayOf(raw.coverage) ?? []).map((c) => String(c));
939
+ return {
940
+ provider: "skillspector",
941
+ providerVersion: pinnedVersion(raw),
942
+ scanMode,
943
+ coverage,
944
+ findings,
945
+ degradedReasons,
946
+ completenessHint
947
+ };
948
+ }
949
+ function parseSkillSpectorSarif(parsed) {
950
+ const raw = asObject(parsed, "SARIF root");
951
+ const runs = arrayOf(raw.runs) ?? [];
952
+ if (runs.length === 0) {
953
+ return {
954
+ provider: "skillspector",
955
+ findings: [],
956
+ degradedReasons: ["SARIF had no runs"]
957
+ };
958
+ }
959
+ const degradedReasons = [];
960
+ const findings = [];
961
+ let providerVersion;
962
+ const coverage = [];
963
+ for (const runUnknown of runs) {
964
+ const run2 = asObject(runUnknown, "SARIF run");
965
+ const tool = asObject(run2.tool ?? {}, "SARIF tool");
966
+ const driver = asObject(tool.driver ?? {}, "SARIF tool.driver");
967
+ if (!providerVersion) {
968
+ const v = typeof driver.semanticVersion === "string" && driver.semanticVersion || typeof driver.version === "string" && driver.version || "";
969
+ if (v) providerVersion = v;
970
+ }
971
+ const results = arrayOf(run2.results) ?? [];
972
+ for (const resUnknown of results) {
973
+ const res = asObject(resUnknown, "SARIF result");
974
+ findings.push({
975
+ providerRuleId: String(res.ruleId ?? "unknown"),
976
+ providerSeverity: String(res.level ?? "warning"),
977
+ message: extractSarifMessage(res),
978
+ locations: extractSarifLocations(res)
979
+ });
980
+ }
981
+ }
982
+ degradedReasons.push("SARIF import: provider-specific fields may be lost vs JSON form");
983
+ return {
984
+ provider: "skillspector",
985
+ providerVersion,
986
+ scanMode: "static",
987
+ coverage,
988
+ findings,
989
+ degradedReasons
990
+ };
991
+ }
992
+ function asObject(v, what) {
993
+ if (v && typeof v === "object" && !Array.isArray(v)) return v;
994
+ throw new Error(`expected object for ${what}`);
995
+ }
996
+ function arrayOf(v) {
997
+ return Array.isArray(v) ? v : void 0;
998
+ }
999
+ function extractLocations(o) {
1000
+ const loc = o.location ?? o.locations ?? o.path;
1001
+ if (typeof loc === "string") return [loc];
1002
+ if (Array.isArray(loc)) return loc.map((x) => String(x));
1003
+ return void 0;
1004
+ }
1005
+ function extractSarifMessage(res) {
1006
+ const msg = res.message;
1007
+ if (msg && typeof msg.text === "string") return msg.text;
1008
+ return void 0;
1009
+ }
1010
+ function extractSarifLocations(res) {
1011
+ const locs = arrayOf(res.locations);
1012
+ if (!locs) return void 0;
1013
+ const out = [];
1014
+ for (const l of locs) {
1015
+ const lo = l;
1016
+ const phys = lo?.physicalLocation;
1017
+ const art = phys?.artifactLocation;
1018
+ const uri = art && typeof art.uri === "string" ? art.uri : void 0;
1019
+ const region = phys?.region;
1020
+ const line = region && typeof region.startLine === "number" ? region.startLine : void 0;
1021
+ if (uri) out.push(line ? `${uri}:${line}` : uri);
1022
+ }
1023
+ return out.length > 0 ? out : void 0;
1024
+ }
1025
+
1026
+ // ../../packages/evidence/src/importEvidence.ts
1027
+ var ZERO_DIGEST = `sha256:${"0".repeat(64)}`;
1028
+ function detectProvider(raw, explicit) {
1029
+ if (explicit) return explicit;
1030
+ const r = raw;
1031
+ if (!r) return "unknown";
1032
+ const topTool = r.tool;
1033
+ const jsonName = typeof r.scanner === "string" && r.scanner || topTool && typeof topTool.name === "string" && topTool.name || "";
1034
+ let sarifName = "";
1035
+ const runs = r.runs;
1036
+ if (Array.isArray(runs) && runs.length > 0) {
1037
+ const run2 = runs[0];
1038
+ const tool = run2?.tool;
1039
+ const driver = tool?.driver;
1040
+ if (driver && typeof driver.name === "string") sarifName = driver.name;
1041
+ }
1042
+ if (/skillspector/i.test(String(jsonName)) || /skillspector/i.test(sarifName)) {
1043
+ return "skillspector";
1044
+ }
1045
+ return "unknown";
1046
+ }
1047
+ function importEvidence(rawText, opts = {}) {
1048
+ const format = opts.format ?? (looksLikeSarif(rawText) ? "sarif" : "json");
1049
+ const rawReportDigest = sha256(rawText);
1050
+ let parsed;
1051
+ try {
1052
+ parsed = JSON.parse(rawText);
1053
+ } catch {
1054
+ return failClosed(opts.provider ?? "unknown", rawReportDigest, [
1055
+ `report is not valid JSON (format=${format})`
1056
+ ]);
1057
+ }
1058
+ const provider = detectProvider(parsed, opts.provider);
1059
+ let result;
1060
+ try {
1061
+ if (provider === "skillspector") {
1062
+ result = format === "sarif" ? parseSkillSpectorSarif(parsed) : parseSkillSpectorJson(parsed);
1063
+ } else {
1064
+ return failClosed(provider, rawReportDigest, [
1065
+ `no adapter for provider "${provider}"; evidence not interpreted`
1066
+ ]);
1067
+ }
1068
+ } catch (err2) {
1069
+ return failClosed(provider, rawReportDigest, [
1070
+ `adapter error: ${err2.message}`
1071
+ ]);
1072
+ }
1073
+ return finalizeEnvelope(result, rawReportDigest);
1074
+ }
1075
+ function failClosed(provider, rawReportDigest, reasons) {
1076
+ return {
1077
+ schema_version: EVIDENCE_SCHEMA_VERSION,
1078
+ provider: provider || "unknown",
1079
+ providerVersion: "unknown",
1080
+ artifactDigest: ZERO_DIGEST,
1081
+ scanMode: "static",
1082
+ coverage: [],
1083
+ completeness: "failed",
1084
+ findings: [],
1085
+ rawReportDigest,
1086
+ degradedReasons: reasons
1087
+ };
1088
+ }
1089
+ function finalizeEnvelope(r, rawReportDigest) {
1090
+ const degradedReasons = [...r.degradedReasons ?? []];
1091
+ const rank = { complete: 0, partial: 1, degraded: 2, failed: 3 };
1092
+ const rankToCompleteness = ["complete", "partial", "degraded", "failed"];
1093
+ let level = rank[r.completenessHint ?? (degradedReasons.length > 0 ? "degraded" : "complete")];
1094
+ let providerVersion = r.providerVersion?.trim() || "";
1095
+ if (!providerVersion) {
1096
+ providerVersion = "unknown";
1097
+ degradedReasons.push("provider version not pinned (no release/commit reported)");
1098
+ level = Math.max(level, rank.degraded);
1099
+ }
1100
+ const completeness = rankToCompleteness[level];
1101
+ return {
1102
+ schema_version: EVIDENCE_SCHEMA_VERSION,
1103
+ provider: r.provider,
1104
+ providerVersion,
1105
+ artifactDigest: r.artifactDigest ?? ZERO_DIGEST,
1106
+ scanMode: r.scanMode ?? "static",
1107
+ coverage: r.coverage ?? [],
1108
+ completeness,
1109
+ findings: r.findings,
1110
+ rawReportDigest,
1111
+ startedAt: r.startedAt,
1112
+ finishedAt: r.finishedAt,
1113
+ degradedReasons
1114
+ };
1115
+ }
1116
+ function looksLikeSarif(text) {
1117
+ return /"runs"\s*:/.test(text) && /sarif/i.test(text);
1118
+ }
1119
+
898
1120
  // ../../packages/static-analyzer/src/detectors/unpinnedPackage.ts
899
1121
  function detectUnpinnedPackage(ctx) {
900
1122
  const { binding } = ctx;
@@ -4658,228 +4880,6 @@ function renderTrustPacket(summary, toolVersion, style = DEFAULT_STYLE) {
4658
4880
  return lines.join("\n");
4659
4881
  }
4660
4882
 
4661
- // ../../packages/evidence/src/types.ts
4662
- var EVIDENCE_SCHEMA_VERSION = "calllint.evidence-provider.v0";
4663
-
4664
- // ../../packages/evidence/src/providers/skillspector.ts
4665
- function pinnedVersion(raw) {
4666
- const tool = raw.tool;
4667
- const commit = typeof raw.commit === "string" && raw.commit || tool && typeof tool.commit === "string" && tool.commit || "";
4668
- if (commit) return `git:${commit}`;
4669
- const version = typeof raw.version === "string" && raw.version || tool && typeof tool.version === "string" && tool.version || "";
4670
- return version || void 0;
4671
- }
4672
- function parseSkillSpectorJson(parsed) {
4673
- const raw = asObject(parsed, "SkillSpector JSON root");
4674
- const degradedReasons = [];
4675
- const usedLlm = raw.llm_used === true || raw.llmUsed === true;
4676
- const scanMode = usedLlm ? "llm" : "static";
4677
- const rawFindings = arrayOf(raw.findings) ?? arrayOf(raw.results) ?? [];
4678
- const findings = rawFindings.map((f) => {
4679
- const o = asObject(f, "SkillSpector finding");
4680
- return {
4681
- providerRuleId: String(o.rule_id ?? o.ruleId ?? o.id ?? "unknown"),
4682
- providerSeverity: String(o.severity ?? o.level ?? "unknown"),
4683
- message: typeof o.message === "string" ? o.message : void 0,
4684
- locations: extractLocations(o)
4685
- };
4686
- });
4687
- let completenessHint;
4688
- const status = String(raw.status ?? raw.scan_status ?? "").toLowerCase();
4689
- if (status && status !== "complete" && status !== "completed" && status !== "success") {
4690
- degradedReasons.push(`SkillSpector reported status "${status}"`);
4691
- completenessHint = status === "partial" ? "partial" : "degraded";
4692
- }
4693
- if (raw.partial === true) {
4694
- degradedReasons.push("SkillSpector reported a partial scan");
4695
- completenessHint = completenessHint ?? "partial";
4696
- }
4697
- if (raw.degraded === true) {
4698
- degradedReasons.push("SkillSpector reported a degraded scan");
4699
- completenessHint = "degraded";
4700
- }
4701
- const coverage = (arrayOf(raw.categories) ?? arrayOf(raw.coverage) ?? []).map((c) => String(c));
4702
- return {
4703
- provider: "skillspector",
4704
- providerVersion: pinnedVersion(raw),
4705
- scanMode,
4706
- coverage,
4707
- findings,
4708
- degradedReasons,
4709
- completenessHint
4710
- };
4711
- }
4712
- function parseSkillSpectorSarif(parsed) {
4713
- const raw = asObject(parsed, "SARIF root");
4714
- const runs = arrayOf(raw.runs) ?? [];
4715
- if (runs.length === 0) {
4716
- return {
4717
- provider: "skillspector",
4718
- findings: [],
4719
- degradedReasons: ["SARIF had no runs"]
4720
- };
4721
- }
4722
- const degradedReasons = [];
4723
- const findings = [];
4724
- let providerVersion;
4725
- const coverage = [];
4726
- for (const runUnknown of runs) {
4727
- const run2 = asObject(runUnknown, "SARIF run");
4728
- const tool = asObject(run2.tool ?? {}, "SARIF tool");
4729
- const driver = asObject(tool.driver ?? {}, "SARIF tool.driver");
4730
- if (!providerVersion) {
4731
- const v = typeof driver.semanticVersion === "string" && driver.semanticVersion || typeof driver.version === "string" && driver.version || "";
4732
- if (v) providerVersion = v;
4733
- }
4734
- const results = arrayOf(run2.results) ?? [];
4735
- for (const resUnknown of results) {
4736
- const res = asObject(resUnknown, "SARIF result");
4737
- findings.push({
4738
- providerRuleId: String(res.ruleId ?? "unknown"),
4739
- providerSeverity: String(res.level ?? "warning"),
4740
- message: extractSarifMessage(res),
4741
- locations: extractSarifLocations(res)
4742
- });
4743
- }
4744
- }
4745
- degradedReasons.push("SARIF import: provider-specific fields may be lost vs JSON form");
4746
- return {
4747
- provider: "skillspector",
4748
- providerVersion,
4749
- scanMode: "static",
4750
- coverage,
4751
- findings,
4752
- degradedReasons
4753
- };
4754
- }
4755
- function asObject(v, what) {
4756
- if (v && typeof v === "object" && !Array.isArray(v)) return v;
4757
- throw new Error(`expected object for ${what}`);
4758
- }
4759
- function arrayOf(v) {
4760
- return Array.isArray(v) ? v : void 0;
4761
- }
4762
- function extractLocations(o) {
4763
- const loc = o.location ?? o.locations ?? o.path;
4764
- if (typeof loc === "string") return [loc];
4765
- if (Array.isArray(loc)) return loc.map((x) => String(x));
4766
- return void 0;
4767
- }
4768
- function extractSarifMessage(res) {
4769
- const msg = res.message;
4770
- if (msg && typeof msg.text === "string") return msg.text;
4771
- return void 0;
4772
- }
4773
- function extractSarifLocations(res) {
4774
- const locs = arrayOf(res.locations);
4775
- if (!locs) return void 0;
4776
- const out = [];
4777
- for (const l of locs) {
4778
- const lo = l;
4779
- const phys = lo?.physicalLocation;
4780
- const art = phys?.artifactLocation;
4781
- const uri = art && typeof art.uri === "string" ? art.uri : void 0;
4782
- const region = phys?.region;
4783
- const line = region && typeof region.startLine === "number" ? region.startLine : void 0;
4784
- if (uri) out.push(line ? `${uri}:${line}` : uri);
4785
- }
4786
- return out.length > 0 ? out : void 0;
4787
- }
4788
-
4789
- // ../../packages/evidence/src/importEvidence.ts
4790
- var ZERO_DIGEST = `sha256:${"0".repeat(64)}`;
4791
- function detectProvider(raw, explicit) {
4792
- if (explicit) return explicit;
4793
- const r = raw;
4794
- if (!r) return "unknown";
4795
- const topTool = r.tool;
4796
- const jsonName = typeof r.scanner === "string" && r.scanner || topTool && typeof topTool.name === "string" && topTool.name || "";
4797
- let sarifName = "";
4798
- const runs = r.runs;
4799
- if (Array.isArray(runs) && runs.length > 0) {
4800
- const run2 = runs[0];
4801
- const tool = run2?.tool;
4802
- const driver = tool?.driver;
4803
- if (driver && typeof driver.name === "string") sarifName = driver.name;
4804
- }
4805
- if (/skillspector/i.test(String(jsonName)) || /skillspector/i.test(sarifName)) {
4806
- return "skillspector";
4807
- }
4808
- return "unknown";
4809
- }
4810
- function importEvidence(rawText, opts = {}) {
4811
- const format = opts.format ?? (looksLikeSarif(rawText) ? "sarif" : "json");
4812
- const rawReportDigest = sha256(rawText);
4813
- let parsed;
4814
- try {
4815
- parsed = JSON.parse(rawText);
4816
- } catch {
4817
- return failClosed(opts.provider ?? "unknown", rawReportDigest, [
4818
- `report is not valid JSON (format=${format})`
4819
- ]);
4820
- }
4821
- const provider = detectProvider(parsed, opts.provider);
4822
- let result;
4823
- try {
4824
- if (provider === "skillspector") {
4825
- result = format === "sarif" ? parseSkillSpectorSarif(parsed) : parseSkillSpectorJson(parsed);
4826
- } else {
4827
- return failClosed(provider, rawReportDigest, [
4828
- `no adapter for provider "${provider}"; evidence not interpreted`
4829
- ]);
4830
- }
4831
- } catch (err2) {
4832
- return failClosed(provider, rawReportDigest, [
4833
- `adapter error: ${err2.message}`
4834
- ]);
4835
- }
4836
- return finalizeEnvelope(result, rawReportDigest);
4837
- }
4838
- function failClosed(provider, rawReportDigest, reasons) {
4839
- return {
4840
- schema_version: EVIDENCE_SCHEMA_VERSION,
4841
- provider: provider || "unknown",
4842
- providerVersion: "unknown",
4843
- artifactDigest: ZERO_DIGEST,
4844
- scanMode: "static",
4845
- coverage: [],
4846
- completeness: "failed",
4847
- findings: [],
4848
- rawReportDigest,
4849
- degradedReasons: reasons
4850
- };
4851
- }
4852
- function finalizeEnvelope(r, rawReportDigest) {
4853
- const degradedReasons = [...r.degradedReasons ?? []];
4854
- const rank = { complete: 0, partial: 1, degraded: 2, failed: 3 };
4855
- const rankToCompleteness = ["complete", "partial", "degraded", "failed"];
4856
- let level = rank[r.completenessHint ?? (degradedReasons.length > 0 ? "degraded" : "complete")];
4857
- let providerVersion = r.providerVersion?.trim() || "";
4858
- if (!providerVersion) {
4859
- providerVersion = "unknown";
4860
- degradedReasons.push("provider version not pinned (no release/commit reported)");
4861
- level = Math.max(level, rank.degraded);
4862
- }
4863
- const completeness = rankToCompleteness[level];
4864
- return {
4865
- schema_version: EVIDENCE_SCHEMA_VERSION,
4866
- provider: r.provider,
4867
- providerVersion,
4868
- artifactDigest: r.artifactDigest ?? ZERO_DIGEST,
4869
- scanMode: r.scanMode ?? "static",
4870
- coverage: r.coverage ?? [],
4871
- completeness,
4872
- findings: r.findings,
4873
- rawReportDigest,
4874
- startedAt: r.startedAt,
4875
- finishedAt: r.finishedAt,
4876
- degradedReasons
4877
- };
4878
- }
4879
- function looksLikeSarif(text) {
4880
- return /"runs"\s*:/.test(text) && /sarif/i.test(text);
4881
- }
4882
-
4883
4883
  // src/exitCode.ts
4884
4884
  function exitCodeFor(summary, policy) {
4885
4885
  const verdict = summary.verdict;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "calllint",
3
- "version": "1.5.1",
3
+ "version": "1.7.0",
4
4
  "description": "Evidence-backed security verdicts for MCP servers and agent tools. Lint agent tool-call risk before tools run — SAFE / REVIEW / BLOCK / UNKNOWN, with evidence. Never executes the server it judges.",
5
5
  "keywords": [
6
6
  "mcp",