calllint 1.6.0 → 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.
- package/dist/index.js +222 -222
- 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.
|
|
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",
|