@cejel/cejel 0.1.3 → 0.1.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/LICENSE +656 -10
- package/README.md +92 -14
- package/dist/{chunk-QQVCIG4N.js → chunk-A7NZKJ5H.js} +1377 -2708
- package/dist/index.js +39 -13
- package/dist/mcp/index.js +217 -217
- package/package.json +12 -8
|
@@ -29,456 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
mod
|
|
30
30
|
));
|
|
31
31
|
|
|
32
|
-
//
|
|
33
|
-
var EXTERNAL_FINDINGS_DISPLAY_LIMIT = 10;
|
|
34
|
-
var SEVERITY_RANK = {
|
|
35
|
-
critical: 0,
|
|
36
|
-
warning: 1,
|
|
37
|
-
info: 2
|
|
38
|
-
};
|
|
39
|
-
function formatExternalSourceLabel(source) {
|
|
40
|
-
return source.startsWith("sarif:") ? source.slice("sarif:".length) : source;
|
|
41
|
-
}
|
|
42
|
-
function summarizeExternalSources(consumedSignals) {
|
|
43
|
-
const bySource = /* @__PURE__ */ new Map();
|
|
44
|
-
for (const signal of consumedSignals) {
|
|
45
|
-
const entry = bySource.get(signal.source) ?? { findingCount: 0, dimensions: /* @__PURE__ */ new Set() };
|
|
46
|
-
entry.findingCount += signal.findingCount;
|
|
47
|
-
entry.dimensions.add(signal.dimension);
|
|
48
|
-
bySource.set(signal.source, entry);
|
|
49
|
-
}
|
|
50
|
-
return Array.from(bySource.entries()).map(([source, { findingCount, dimensions }]) => ({
|
|
51
|
-
source,
|
|
52
|
-
label: formatExternalSourceLabel(source),
|
|
53
|
-
findingCount,
|
|
54
|
-
dimensions: Array.from(dimensions).sort()
|
|
55
|
-
})).sort((a, b) => a.source.localeCompare(b.source));
|
|
56
|
-
}
|
|
57
|
-
function formatExternalSourceLine(summary) {
|
|
58
|
-
const noun = summary.findingCount === 1 ? "finding" : "findings";
|
|
59
|
-
return `${summary.label}: ${summary.findingCount} ${noun} ingested (folded into ${summary.dimensions.join(", ")})`;
|
|
60
|
-
}
|
|
61
|
-
function collectExternalFindings(consumedSignals) {
|
|
62
|
-
const findings = [];
|
|
63
|
-
for (const signal of consumedSignals) {
|
|
64
|
-
for (const finding of signal.findings) {
|
|
65
|
-
findings.push({
|
|
66
|
-
source: signal.source,
|
|
67
|
-
label: formatExternalSourceLabel(signal.source),
|
|
68
|
-
dimension: signal.dimension,
|
|
69
|
-
severity: finding.severity,
|
|
70
|
-
ruleId: finding.ruleId,
|
|
71
|
-
message: finding.message,
|
|
72
|
-
...finding.location ? { location: finding.location } : {}
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return findings.sort((a, b) => {
|
|
77
|
-
const bySeverity = SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity];
|
|
78
|
-
if (bySeverity !== 0) return bySeverity;
|
|
79
|
-
const bySource = a.source.localeCompare(b.source);
|
|
80
|
-
if (bySource !== 0) return bySource;
|
|
81
|
-
return a.ruleId.localeCompare(b.ruleId);
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// ../witan/src/html.ts
|
|
86
|
-
function renderWitanHtmlReport(report) {
|
|
87
|
-
const codeCriteria = criteriaByCategory(report, "code_trust");
|
|
88
|
-
const processCriteria = criteriaByCategory(report, "process_trust");
|
|
89
|
-
const verifiedEvidence = report.criteria.flatMap(
|
|
90
|
-
(criterion) => criterion.status === "verified" ? criterion.evidence.map((evidence) => renderEvidenceListItem(criterion, evidence)) : []
|
|
91
|
-
);
|
|
92
|
-
const openItems = report.criteria.flatMap(renderOpenItems);
|
|
93
|
-
const contributingSources = renderContributingSources(report.consumedSignals ?? []);
|
|
94
|
-
const externalSourceSummaries = summarizeExternalSources(report.consumedSignals ?? []);
|
|
95
|
-
const externalFindings = collectExternalFindings(report.consumedSignals ?? []);
|
|
96
|
-
return `<!doctype html>
|
|
97
|
-
<html lang="en">
|
|
98
|
-
<head>
|
|
99
|
-
<meta charset="utf-8">
|
|
100
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
101
|
-
<title>Cejel Trust Certificate - ${escapeHtml(report.productDisplayName)}</title>
|
|
102
|
-
<style>${CERTIFICATE_CSS}</style>
|
|
103
|
-
</head>
|
|
104
|
-
<body>
|
|
105
|
-
<main class="certificate">
|
|
106
|
-
<header class="hero">
|
|
107
|
-
<div class="brand">
|
|
108
|
-
<span class="brand-mark" aria-hidden="true">C</span>
|
|
109
|
-
<span class="brand-name">Cejel / Alfred</span>
|
|
110
|
-
</div>
|
|
111
|
-
<div class="hero-grid">
|
|
112
|
-
<section>
|
|
113
|
-
<p class="eyebrow">Trust Certificate</p>
|
|
114
|
-
<h1>${escapeHtml(report.productDisplayName)}</h1>
|
|
115
|
-
<dl class="meta">
|
|
116
|
-
<div><dt>Date</dt><dd>${escapeHtml(formatDate(report.generatedAt))}</dd></div>
|
|
117
|
-
<div><dt>Run</dt><dd>${escapeHtml(renderRepo(report))}</dd></div>
|
|
118
|
-
<div><dt>Rubric</dt><dd>${escapeHtml(report.rubricVersion)}</dd></div>
|
|
119
|
-
${contributingSources.length > 0 ? `<div><dt>Sources</dt><dd>Incorporates findings from: ${escapeHtml(contributingSources.join(", "))}<ul class="source-counts">${externalSourceSummaries.map((s) => `<li>${escapeHtml(formatExternalSourceLine(s))}</li>`).join("")}</ul></dd></div>` : ""}
|
|
120
|
-
</dl>
|
|
121
|
-
</section>
|
|
122
|
-
<aside class="score-panel" aria-label="Summary trust score">
|
|
123
|
-
<div class="score-badge">Summary</div>
|
|
124
|
-
${report.insufficientSourceReason ? `<div class="verdict">Insufficient source</div>
|
|
125
|
-
<p class="insufficient-note">${escapeHtml(report.insufficientSourceReason)}</p>` : `<div class="score">${formatScore(report.overallScore)}</div>
|
|
126
|
-
<div class="score-unit">/ 4.0 overall</div>
|
|
127
|
-
<div class="verdict">${escapeHtml(renderVerdict(report.overallScore))}</div>
|
|
128
|
-
<div class="subscores">
|
|
129
|
-
<span>Code ${formatScore(report.codeTrustScore)}</span>
|
|
130
|
-
<span>Process ${formatScore(report.processTrustScore)}</span>
|
|
131
|
-
</div>`}
|
|
132
|
-
</aside>
|
|
133
|
-
</div>
|
|
134
|
-
</header>
|
|
135
|
-
|
|
136
|
-
<section class="trust-grid" aria-label="Rubric criteria">
|
|
137
|
-
${renderCriterionColumn("Code trust", codeCriteria)}
|
|
138
|
-
${renderCriterionColumn("Process trust", processCriteria)}
|
|
139
|
-
</section>
|
|
140
|
-
|
|
141
|
-
<section class="evidence-grid" aria-label="Evidence and gaps">
|
|
142
|
-
<article class="evidence-section">
|
|
143
|
-
<h2>Verified evidence</h2>
|
|
144
|
-
<ul>${verifiedEvidence.length > 0 ? verifiedEvidence.join("") : "<li>No verified evidence supplied.</li>"}</ul>
|
|
145
|
-
</article>
|
|
146
|
-
<article class="evidence-section">
|
|
147
|
-
<h2>Open / unverified</h2>
|
|
148
|
-
<ul>${openItems.length > 0 ? openItems.join("") : "<li>No open or unverified criteria supplied.</li>"}</ul>
|
|
149
|
-
</article>
|
|
150
|
-
</section>
|
|
151
|
-
|
|
152
|
-
${externalFindings.length > 0 ? `<section class="external-findings-section" aria-label="External findings">
|
|
153
|
-
<article class="evidence-section">
|
|
154
|
-
<h2>External findings</h2>
|
|
155
|
-
<p class="external-note">Findings surfaced by ingested external scanners, attributed to the tool and the cejel criterion they were folded into \u2014 distinct from cejel's own findings above.</p>
|
|
156
|
-
<ul>${renderExternalFindingItems(externalFindings).join("")}</ul>
|
|
157
|
-
</article>
|
|
158
|
-
</section>` : ""}
|
|
159
|
-
</main>
|
|
160
|
-
</body>
|
|
161
|
-
</html>
|
|
162
|
-
`;
|
|
163
|
-
}
|
|
164
|
-
function renderContributingSources(signals) {
|
|
165
|
-
return Array.from(new Set(signals.map((s) => s.source))).sort();
|
|
166
|
-
}
|
|
167
|
-
function renderExternalFindingItems(findings) {
|
|
168
|
-
const shown = findings.slice(0, EXTERNAL_FINDINGS_DISPLAY_LIMIT);
|
|
169
|
-
const items = shown.map(
|
|
170
|
-
(f) => `<li><strong>${escapeHtml(f.label)} \u2192 ${escapeHtml(f.dimension)}</strong><span>${escapeHtml(f.severity)}: ${escapeHtml(f.ruleId)} \u2014 ${escapeHtml(f.message)}${f.location ? ` (${escapeHtml(f.location)})` : ""}</span></li>`
|
|
171
|
-
);
|
|
172
|
-
const remaining = findings.length - shown.length;
|
|
173
|
-
if (remaining > 0) {
|
|
174
|
-
items.push(`<li><em>...and ${remaining} more \u2014 see report.json for the full list.</em></li>`);
|
|
175
|
-
}
|
|
176
|
-
return items;
|
|
177
|
-
}
|
|
178
|
-
function criteriaByCategory(report, category) {
|
|
179
|
-
return report.criteria.filter((criterion) => criterion.category === category);
|
|
180
|
-
}
|
|
181
|
-
function renderCriterionColumn(title, criteria) {
|
|
182
|
-
const applicable = criteria.filter((criterion) => criterion.status !== "not_applicable");
|
|
183
|
-
const notApplicable = criteria.filter((criterion) => criterion.status === "not_applicable");
|
|
184
|
-
return `<section class="criteria-column">
|
|
185
|
-
<h2>${escapeHtml(title)}</h2>
|
|
186
|
-
<div class="criteria-list">
|
|
187
|
-
${applicable.map(renderCriterionCard).join("")}
|
|
188
|
-
</div>
|
|
189
|
-
${notApplicable.length > 0 ? renderNotApplicableGroup(notApplicable) : ""}
|
|
190
|
-
</section>`;
|
|
191
|
-
}
|
|
192
|
-
function renderNotApplicableGroup(criteria) {
|
|
193
|
-
return `<div class="na-group">
|
|
194
|
-
<h3 class="na-heading">Not applicable to this repository</h3>
|
|
195
|
-
<ul class="na-list">
|
|
196
|
-
${criteria.map(renderNotApplicableItem).join("")}
|
|
197
|
-
</ul>
|
|
198
|
-
</div>`;
|
|
199
|
-
}
|
|
200
|
-
function renderNotApplicableItem(criterion) {
|
|
201
|
-
const reason = criterion.notes ?? "Not applicable to this repository.";
|
|
202
|
-
return `<li><span class="na-id">${escapeHtml(criterion.id)}</span> ${escapeHtml(criterion.title)} \u2014 <span class="na-reason">${escapeHtml(reason)}</span></li>`;
|
|
203
|
-
}
|
|
204
|
-
function renderCriterionCard(criterion) {
|
|
205
|
-
const evidence = [
|
|
206
|
-
...criterion.evidence.map(renderEvidencePointer),
|
|
207
|
-
...criterion.findings.map((finding) => renderFindingEvidence(finding))
|
|
208
|
-
];
|
|
209
|
-
const metrics = criterion.metrics.map(renderMetric);
|
|
210
|
-
return `<article class="criterion">
|
|
211
|
-
<div class="criterion-top">
|
|
212
|
-
<div>
|
|
213
|
-
<div class="criterion-id">${escapeHtml(criterion.id)}</div>
|
|
214
|
-
<h3>${escapeHtml(criterion.title)}</h3>
|
|
215
|
-
</div>
|
|
216
|
-
${renderStatusChip(criterion.status)}
|
|
217
|
-
</div>
|
|
218
|
-
<div class="criterion-score">${criterion.status === "not_applicable" ? "N/A" : criterion.status === "insufficient_data" ? "No data" : formatScore(criterion.score)}</div>
|
|
219
|
-
<ul class="criterion-metrics">
|
|
220
|
-
${metrics.length > 0 ? metrics.map((item) => `<li>${item}</li>`).join("") : "<li>No measured depth metrics supplied.</li>"}
|
|
221
|
-
</ul>
|
|
222
|
-
<ul class="criterion-evidence">
|
|
223
|
-
${evidence.length > 0 ? evidence.map((item) => `<li>${item}</li>`).join("") : "<li>No concrete evidence supplied.</li>"}
|
|
224
|
-
</ul>
|
|
225
|
-
</article>`;
|
|
226
|
-
}
|
|
227
|
-
function renderMetric(metric2) {
|
|
228
|
-
const max = metric2.max ? `/${formatMetricValue(metric2.max)}` : "";
|
|
229
|
-
const unit = metric2.unit ? ` ${escapeHtml(metric2.unit)}` : "";
|
|
230
|
-
return `<strong>${escapeHtml(metric2.label)}</strong><span>${formatMetricValue(metric2.value)}${max}${unit}</span>`;
|
|
231
|
-
}
|
|
232
|
-
function renderStatusChip(status) {
|
|
233
|
-
return `<span class="status" data-status="${status}">${status}</span>`;
|
|
234
|
-
}
|
|
235
|
-
function renderEvidenceListItem(criterion, evidence) {
|
|
236
|
-
return `<li><strong>${escapeHtml(criterion.id)} - ${escapeHtml(criterion.title)}</strong><span>${renderEvidencePointer(evidence)}</span></li>`;
|
|
237
|
-
}
|
|
238
|
-
function renderOpenItems(criterion) {
|
|
239
|
-
const findingItems = criterion.findings.map(
|
|
240
|
-
(finding) => `<li><strong>${escapeHtml(criterion.id)} - ${escapeHtml(criterion.title)}</strong><span>${escapeHtml(finding.severity)}: ${escapeHtml(finding.summary)} (${renderEvidencePointer(finding.evidence)})</span></li>`
|
|
241
|
-
);
|
|
242
|
-
if ((criterion.status === "unverified" || criterion.status === "insufficient_data") && criterion.evidence.length === 0 && criterion.findings.length === 0) {
|
|
243
|
-
const message = criterion.status === "insufficient_data" ? "Insufficient data \u2014 no measurable signal; excluded from composite (unmeasured, not inapplicable)." : "No concrete evidence supplied.";
|
|
244
|
-
return [
|
|
245
|
-
`<li><strong>${escapeHtml(criterion.id)} - ${escapeHtml(criterion.title)}</strong><span>${escapeHtml(message)}</span></li>`
|
|
246
|
-
];
|
|
247
|
-
}
|
|
248
|
-
if (criterion.status === "verified") return [];
|
|
249
|
-
return findingItems;
|
|
250
|
-
}
|
|
251
|
-
function renderFindingEvidence(finding) {
|
|
252
|
-
return `${escapeHtml(finding.severity)}: ${escapeHtml(finding.summary)} (${renderEvidencePointer(
|
|
253
|
-
finding.evidence
|
|
254
|
-
)})`;
|
|
255
|
-
}
|
|
256
|
-
function renderEvidencePointer(evidence) {
|
|
257
|
-
const target = evidence.url ?? renderPathEvidenceTarget(evidence);
|
|
258
|
-
const label = escapeHtml(evidence.label);
|
|
259
|
-
if (evidence.url) {
|
|
260
|
-
return `<a href="${escapeAttribute(evidence.url)}">${label}</a>`;
|
|
261
|
-
}
|
|
262
|
-
return [label, target ? `<code>${escapeHtml(target)}</code>` : void 0].filter(Boolean).join(" ");
|
|
263
|
-
}
|
|
264
|
-
function renderPathEvidenceTarget(evidence) {
|
|
265
|
-
const pathTarget = evidence.path ? `${evidence.path}${evidence.line ? `:${evidence.line}` : ""}` : void 0;
|
|
266
|
-
const hashTarget = evidence.contentHash ? `sha256:${evidence.contentHash.slice(0, 12)}` : void 0;
|
|
267
|
-
return [pathTarget, hashTarget].filter(Boolean).join(" \xB7 ");
|
|
268
|
-
}
|
|
269
|
-
function renderRepo(report) {
|
|
270
|
-
const repo = report.repo.path ?? report.repo.url ?? "unknown";
|
|
271
|
-
return report.repo.headSha ? `${repo} @ ${report.repo.headSha}` : repo;
|
|
272
|
-
}
|
|
273
|
-
function renderVerdict(score) {
|
|
274
|
-
if (score >= 3.5) return "Verified";
|
|
275
|
-
if (score >= 2.5) return "Conditional";
|
|
276
|
-
if (score >= 1.5) return "At risk";
|
|
277
|
-
return "Unverified";
|
|
278
|
-
}
|
|
279
|
-
function renderReportVerdict(report) {
|
|
280
|
-
if (report.insufficientSourceReason) return "Insufficient source";
|
|
281
|
-
return renderVerdict(report.overallScore);
|
|
282
|
-
}
|
|
283
|
-
function formatScore(score) {
|
|
284
|
-
return score.toFixed(1);
|
|
285
|
-
}
|
|
286
|
-
function formatMetricValue(value) {
|
|
287
|
-
return Number.isInteger(value) ? value.toString() : value.toFixed(2);
|
|
288
|
-
}
|
|
289
|
-
function formatDate(value) {
|
|
290
|
-
return value.slice(0, 10);
|
|
291
|
-
}
|
|
292
|
-
function escapeHtml(value) {
|
|
293
|
-
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
294
|
-
}
|
|
295
|
-
function escapeAttribute(value) {
|
|
296
|
-
return escapeHtml(value);
|
|
297
|
-
}
|
|
298
|
-
var CERTIFICATE_CSS = `
|
|
299
|
-
:root {
|
|
300
|
-
color-scheme: dark;
|
|
301
|
-
--steel: #16212a;
|
|
302
|
-
--surface: #1d2b35;
|
|
303
|
-
--surface-2: #273946;
|
|
304
|
-
--line: rgba(238, 244, 247, .13);
|
|
305
|
-
--line-strong: rgba(238, 244, 247, .22);
|
|
306
|
-
--text: #eef4f7;
|
|
307
|
-
--muted: #b7c5cc;
|
|
308
|
-
--faint: #8799a4;
|
|
309
|
-
--teal: #2fc8a6;
|
|
310
|
-
--teal-weak: rgba(47, 200, 166, .14);
|
|
311
|
-
--periwinkle: #93a6da;
|
|
312
|
-
--periwinkle-weak: rgba(147, 166, 218, .16);
|
|
313
|
-
--warn: #e7bf72;
|
|
314
|
-
--warn-weak: rgba(231, 191, 114, .16);
|
|
315
|
-
--danger: #f09a8f;
|
|
316
|
-
--danger-weak: rgba(240, 154, 143, .14);
|
|
317
|
-
--quiet: rgba(238, 244, 247, .08);
|
|
318
|
-
--serif: "Instrument Serif", Georgia, "Times New Roman", serif;
|
|
319
|
-
--sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
320
|
-
--mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
321
|
-
}
|
|
322
|
-
* { box-sizing: border-box; }
|
|
323
|
-
body {
|
|
324
|
-
margin: 0;
|
|
325
|
-
background: var(--steel);
|
|
326
|
-
color: var(--text);
|
|
327
|
-
font-family: var(--sans);
|
|
328
|
-
line-height: 1.55;
|
|
329
|
-
-webkit-font-smoothing: antialiased;
|
|
330
|
-
}
|
|
331
|
-
.certificate { max-width: 1120px; margin: 0 auto; padding: 44px 32px 64px; }
|
|
332
|
-
.hero { border-bottom: 1px solid var(--line); padding-bottom: 38px; }
|
|
333
|
-
.brand { display: flex; align-items: center; gap: 12px; margin-bottom: 44px; }
|
|
334
|
-
.brand-mark {
|
|
335
|
-
display: inline-flex; align-items: center; justify-content: center;
|
|
336
|
-
width: 34px; height: 34px; border-radius: 8px;
|
|
337
|
-
background: var(--teal); color: #06231d; font-family: var(--serif); font-size: 24px;
|
|
338
|
-
}
|
|
339
|
-
.brand-name { font-family: var(--serif); font-size: 24px; }
|
|
340
|
-
.hero-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 36px; align-items: end; }
|
|
341
|
-
.eyebrow {
|
|
342
|
-
margin: 0 0 14px; color: var(--teal); font-family: var(--mono);
|
|
343
|
-
font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
|
|
344
|
-
}
|
|
345
|
-
h1, h2, h3, p { margin-top: 0; }
|
|
346
|
-
h1 { margin-bottom: 24px; font-family: var(--serif); font-size: 64px; line-height: 1; font-weight: 400; letter-spacing: 0; }
|
|
347
|
-
.meta { display: grid; gap: 10px; margin: 0; max-width: 780px; }
|
|
348
|
-
.meta div { display: grid; grid-template-columns: 86px minmax(0, 1fr); gap: 16px; }
|
|
349
|
-
dt { color: var(--faint); font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: .12em; }
|
|
350
|
-
dd { margin: 0; color: var(--muted); overflow-wrap: anywhere; }
|
|
351
|
-
.score-panel { border: 1px solid var(--line-strong); border-radius: 8px; padding: 24px; background: var(--surface); }
|
|
352
|
-
.score-badge {
|
|
353
|
-
display: inline-flex; margin-bottom: 14px; border: 1px solid rgba(147, 166, 218, .38);
|
|
354
|
-
border-radius: 999px; padding: 5px 10px; color: var(--periwinkle);
|
|
355
|
-
background: var(--periwinkle-weak); font-family: var(--mono); font-size: 12px;
|
|
356
|
-
}
|
|
357
|
-
.score { display: inline; font-family: var(--mono); font-size: 56px; line-height: 1; color: var(--teal); }
|
|
358
|
-
.score-unit { display: inline; margin-left: 6px; color: var(--faint); font-family: var(--mono); }
|
|
359
|
-
.verdict { margin-top: 12px; font-family: var(--serif); font-size: 30px; color: var(--periwinkle); }
|
|
360
|
-
.insufficient-note { margin-top: 10px; color: var(--muted); font-size: 13px; line-height: 1.5; }
|
|
361
|
-
.subscores { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 18px; color: var(--muted); font-family: var(--mono); font-size: 12px; }
|
|
362
|
-
.source-counts { margin: 8px 0 0; padding-left: 18px; font-family: var(--mono); font-size: 12px; color: var(--muted); }
|
|
363
|
-
.trust-grid, .evidence-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; margin-top: 28px; }
|
|
364
|
-
.external-findings-section { margin-top: 18px; }
|
|
365
|
-
.external-note { margin: 0 0 14px; color: var(--muted); font-size: 13px; }
|
|
366
|
-
.criteria-column, .evidence-section { border: 1px solid var(--line); border-radius: 8px; background: var(--surface); padding: 22px; }
|
|
367
|
-
h2 { font-family: var(--serif); font-size: 30px; font-weight: 400; letter-spacing: 0; margin-bottom: 18px; }
|
|
368
|
-
.criteria-list { display: grid; gap: 12px; }
|
|
369
|
-
.na-group { margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--line-strong); }
|
|
370
|
-
.na-heading { font-family: var(--sans); font-size: 12px; font-weight: 650; letter-spacing: .04em; text-transform: uppercase; color: var(--faint); margin: 0 0 10px; }
|
|
371
|
-
.na-list { display: grid; gap: 8px; font-size: 13px; }
|
|
372
|
-
.na-list li { margin: 0; color: var(--muted); }
|
|
373
|
-
.na-id { color: var(--faint); font-family: var(--mono); font-size: 11px; margin-right: 6px; }
|
|
374
|
-
.na-reason { color: var(--muted); }
|
|
375
|
-
.criterion { border: 1px solid var(--line); border-radius: 8px; padding: 16px; background: var(--surface-2); }
|
|
376
|
-
.criterion-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; }
|
|
377
|
-
.criterion-id { color: var(--periwinkle); font-family: var(--mono); font-size: 12px; margin-bottom: 4px; }
|
|
378
|
-
h3 { font-size: 15px; line-height: 1.35; font-weight: 600; margin-bottom: 0; }
|
|
379
|
-
.criterion-score { margin-top: 12px; color: var(--text); font-family: var(--mono); font-size: 24px; }
|
|
380
|
-
.criterion-metrics { display: grid; gap: 7px; margin-top: 10px; padding: 0; list-style: none; font-size: 12px; }
|
|
381
|
-
.criterion-metrics li { display: flex; justify-content: space-between; gap: 12px; border-bottom: 1px solid rgba(238, 244, 247, .08); padding-bottom: 6px; }
|
|
382
|
-
.criterion-metrics strong { color: var(--text); font-weight: 650; }
|
|
383
|
-
.criterion-metrics span { white-space: nowrap; color: var(--muted); }
|
|
384
|
-
.status { flex: none; border-radius: 999px; padding: 4px 9px; font-family: var(--mono); font-size: 11px; border: 1px solid var(--line-strong); }
|
|
385
|
-
.status[data-status="verified"] { color: var(--teal); background: var(--teal-weak); border-color: rgba(47, 200, 166, .42); }
|
|
386
|
-
.status[data-status="info"] { color: var(--periwinkle); background: var(--periwinkle-weak); border-color: rgba(147, 166, 218, .4); }
|
|
387
|
-
.status[data-status="warning"] { color: var(--warn); background: var(--warn-weak); border-color: rgba(231, 191, 114, .44); }
|
|
388
|
-
.status[data-status="critical"] { color: var(--danger); background: var(--danger-weak); border-color: rgba(240, 154, 143, .46); }
|
|
389
|
-
.status[data-status="unverified"] { color: var(--muted); background: var(--quiet); }
|
|
390
|
-
.status[data-status="insufficient_data"] { color: var(--muted); background: var(--quiet); border-style: dashed; }
|
|
391
|
-
ul { margin: 0; padding-left: 18px; }
|
|
392
|
-
li { margin: 8px 0; color: var(--muted); }
|
|
393
|
-
.criterion-evidence { margin-top: 12px; font-size: 13px; }
|
|
394
|
-
.evidence-section li strong { display: block; color: var(--text); font-size: 14px; }
|
|
395
|
-
.evidence-section li span { display: block; margin-top: 2px; font-size: 13px; }
|
|
396
|
-
code { color: var(--periwinkle); font-family: var(--mono); font-size: .92em; overflow-wrap: anywhere; }
|
|
397
|
-
a { color: var(--teal); text-decoration: none; }
|
|
398
|
-
a:hover { text-decoration: underline; text-underline-offset: 2px; }
|
|
399
|
-
@media (max-width: 840px) {
|
|
400
|
-
.certificate { padding: 28px 18px 48px; }
|
|
401
|
-
.hero-grid, .trust-grid, .evidence-grid { grid-template-columns: 1fr; }
|
|
402
|
-
h1 { font-size: 46px; }
|
|
403
|
-
}
|
|
404
|
-
`;
|
|
405
|
-
|
|
406
|
-
// ../witan/src/badge.ts
|
|
407
|
-
var VERDICT_COLOR = {
|
|
408
|
-
Verified: "brightgreen",
|
|
409
|
-
Conditional: "yellow",
|
|
410
|
-
"At risk": "orange",
|
|
411
|
-
Unverified: "red",
|
|
412
|
-
"Insufficient source": "lightgrey"
|
|
413
|
-
};
|
|
414
|
-
var VERDICT_SVG_FILL = {
|
|
415
|
-
Verified: "#2fc86a",
|
|
416
|
-
Conditional: "#dfb92f",
|
|
417
|
-
"At risk": "#e08a3c",
|
|
418
|
-
Unverified: "#d64545",
|
|
419
|
-
"Insufficient source": "#8c8c8c"
|
|
420
|
-
};
|
|
421
|
-
function badgeMessage(report, verdict) {
|
|
422
|
-
if (report.insufficientSourceReason) return "unrated: no source";
|
|
423
|
-
return `${formatScore2(report.overallScore)}/4.0 ${verdict.toLowerCase()}`;
|
|
424
|
-
}
|
|
425
|
-
function renderWitanBadgeEndpoint(report) {
|
|
426
|
-
const verdict = renderReportVerdict(report);
|
|
427
|
-
return {
|
|
428
|
-
schemaVersion: 1,
|
|
429
|
-
label: "cejel trust",
|
|
430
|
-
message: badgeMessage(report, verdict),
|
|
431
|
-
color: VERDICT_COLOR[verdict] ?? "lightgrey"
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
function renderWitanBadgeSvg(report) {
|
|
435
|
-
const verdict = renderReportVerdict(report);
|
|
436
|
-
const label = "cejel trust";
|
|
437
|
-
const message = badgeMessage(report, verdict);
|
|
438
|
-
const fill = VERDICT_SVG_FILL[verdict] ?? "#8c8c8c";
|
|
439
|
-
const charWidth = 6.5;
|
|
440
|
-
const padding = 10;
|
|
441
|
-
const labelWidth = Math.round(label.length * charWidth + padding);
|
|
442
|
-
const messageWidth = Math.round(message.length * charWidth + padding);
|
|
443
|
-
const totalWidth = labelWidth + messageWidth;
|
|
444
|
-
const height = 20;
|
|
445
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="${height}" role="img" aria-label="${escapeXml(label)}: ${escapeXml(message)}">
|
|
446
|
-
<title>${escapeXml(label)}: ${escapeXml(message)}</title>
|
|
447
|
-
<linearGradient id="witan-badge-smooth" x2="0" y2="100%">
|
|
448
|
-
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
|
449
|
-
<stop offset="1" stop-opacity=".1"/>
|
|
450
|
-
</linearGradient>
|
|
451
|
-
<clipPath id="witan-badge-round">
|
|
452
|
-
<rect width="${totalWidth}" height="${height}" rx="3" fill="#fff"/>
|
|
453
|
-
</clipPath>
|
|
454
|
-
<g clip-path="url(#witan-badge-round)">
|
|
455
|
-
<rect width="${labelWidth}" height="${height}" fill="#555"/>
|
|
456
|
-
<rect x="${labelWidth}" width="${messageWidth}" height="${height}" fill="${fill}"/>
|
|
457
|
-
<rect width="${totalWidth}" height="${height}" fill="url(#witan-badge-smooth)"/>
|
|
458
|
-
</g>
|
|
459
|
-
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="11">
|
|
460
|
-
<text x="${labelWidth / 2}" y="14">${escapeXml(label)}</text>
|
|
461
|
-
<text x="${labelWidth + messageWidth / 2}" y="14">${escapeXml(message)}</text>
|
|
462
|
-
</g>
|
|
463
|
-
</svg>
|
|
464
|
-
`;
|
|
465
|
-
}
|
|
466
|
-
function formatScore2(score) {
|
|
467
|
-
return score.toFixed(1);
|
|
468
|
-
}
|
|
469
|
-
function escapeXml(value) {
|
|
470
|
-
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// ../witan/src/claim-reality.ts
|
|
474
|
-
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
|
475
|
-
import { join } from "path";
|
|
476
|
-
|
|
477
|
-
// ../witan/src/leaderboard.ts
|
|
478
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "fs";
|
|
479
|
-
import { join as join6 } from "path";
|
|
480
|
-
|
|
481
|
-
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
32
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
482
33
|
var external_exports = {};
|
|
483
34
|
__export(external_exports, {
|
|
484
35
|
BRAND: () => BRAND,
|
|
@@ -590,7 +141,7 @@ __export(external_exports, {
|
|
|
590
141
|
void: () => voidType
|
|
591
142
|
});
|
|
592
143
|
|
|
593
|
-
//
|
|
144
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
|
|
594
145
|
var util;
|
|
595
146
|
(function(util2) {
|
|
596
147
|
util2.assertEqual = (_) => {
|
|
@@ -724,7 +275,7 @@ var getParsedType = (data) => {
|
|
|
724
275
|
}
|
|
725
276
|
};
|
|
726
277
|
|
|
727
|
-
//
|
|
278
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
|
|
728
279
|
var ZodIssueCode = util.arrayToEnum([
|
|
729
280
|
"invalid_type",
|
|
730
281
|
"invalid_literal",
|
|
@@ -842,7 +393,7 @@ ZodError.create = (issues) => {
|
|
|
842
393
|
return error;
|
|
843
394
|
};
|
|
844
395
|
|
|
845
|
-
//
|
|
396
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js
|
|
846
397
|
var errorMap = (issue, _ctx) => {
|
|
847
398
|
let message;
|
|
848
399
|
switch (issue.code) {
|
|
@@ -945,7 +496,7 @@ var errorMap = (issue, _ctx) => {
|
|
|
945
496
|
};
|
|
946
497
|
var en_default = errorMap;
|
|
947
498
|
|
|
948
|
-
//
|
|
499
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js
|
|
949
500
|
var overrideErrorMap = en_default;
|
|
950
501
|
function setErrorMap(map) {
|
|
951
502
|
overrideErrorMap = map;
|
|
@@ -954,7 +505,7 @@ function getErrorMap() {
|
|
|
954
505
|
return overrideErrorMap;
|
|
955
506
|
}
|
|
956
507
|
|
|
957
|
-
//
|
|
508
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
958
509
|
var makeIssue = (params) => {
|
|
959
510
|
const { data, path, errorMaps, issueData } = params;
|
|
960
511
|
const fullPath = [...path, ...issueData.path || []];
|
|
@@ -1064,14 +615,14 @@ var isDirty = (x) => x.status === "dirty";
|
|
|
1064
615
|
var isValid = (x) => x.status === "valid";
|
|
1065
616
|
var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
|
|
1066
617
|
|
|
1067
|
-
//
|
|
618
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
|
|
1068
619
|
var errorUtil;
|
|
1069
620
|
(function(errorUtil2) {
|
|
1070
621
|
errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
|
|
1071
622
|
errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
|
|
1072
623
|
})(errorUtil || (errorUtil = {}));
|
|
1073
624
|
|
|
1074
|
-
//
|
|
625
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
1075
626
|
var ParseInputLazyPath = class {
|
|
1076
627
|
constructor(parent, value, path, key) {
|
|
1077
628
|
this._cachedPath = [];
|
|
@@ -4519,849 +4070,7 @@ var coerce = {
|
|
|
4519
4070
|
};
|
|
4520
4071
|
var NEVER = INVALID;
|
|
4521
4072
|
|
|
4522
|
-
//
|
|
4523
|
-
var attestationOutcomeSchema = external_exports.enum([
|
|
4524
|
-
"ATTESTED_READY",
|
|
4525
|
-
"ATTESTED_WITH_GAPS",
|
|
4526
|
-
"NOT_READY",
|
|
4527
|
-
"REVOKED"
|
|
4528
|
-
]);
|
|
4529
|
-
var attestationKindSchema = external_exports.enum(["OPERATOR_READINESS", "EXTERNAL_ASSESSOR_REFERENCE"]);
|
|
4530
|
-
var attestationEvidenceRefKindSchema = external_exports.enum([
|
|
4531
|
-
"runbook_path",
|
|
4532
|
-
"github_run_url",
|
|
4533
|
-
"vercel_deployment_id",
|
|
4534
|
-
"neon_query_evidence",
|
|
4535
|
-
"report_hash",
|
|
4536
|
-
"external_assessor_ref"
|
|
4537
|
-
]);
|
|
4538
|
-
var attestationEvidenceRefSchema = external_exports.object({
|
|
4539
|
-
kind: attestationEvidenceRefKindSchema,
|
|
4540
|
-
/** Redacted reference string (path, URL, ID, or hash). Max 512 chars. */
|
|
4541
|
-
ref: external_exports.string().min(1).max(512),
|
|
4542
|
-
/** Optional one-line redacted description. */
|
|
4543
|
-
note: external_exports.string().max(280).optional()
|
|
4544
|
-
});
|
|
4545
|
-
var createAttestationInputSchema = external_exports.object({
|
|
4546
|
-
studioId: external_exports.string().uuid(),
|
|
4547
|
-
complianceProfileId: external_exports.string().uuid(),
|
|
4548
|
-
productId: external_exports.string().uuid().nullable().optional(),
|
|
4549
|
-
framework: external_exports.string().min(1).max(120),
|
|
4550
|
-
kind: attestationKindSchema,
|
|
4551
|
-
outcome: attestationOutcomeSchema,
|
|
4552
|
-
/** Redacted operator statement; no payloads. */
|
|
4553
|
-
statement: external_exports.string().min(1).max(4e3),
|
|
4554
|
-
evidenceRefs: external_exports.array(attestationEvidenceRefSchema).min(1),
|
|
4555
|
-
supersedesAttestationId: external_exports.string().uuid().nullable().optional(),
|
|
4556
|
-
metadata: external_exports.record(external_exports.unknown()).default({})
|
|
4557
|
-
});
|
|
4558
|
-
|
|
4559
|
-
// ../shared/src/types/standup-provisioning.ts
|
|
4560
|
-
var ScaffoldFileSchema = external_exports.object({
|
|
4561
|
-
path: external_exports.string().min(1),
|
|
4562
|
-
contents: external_exports.string()
|
|
4563
|
-
}).strict();
|
|
4564
|
-
var ScaffoldManifestSchema = external_exports.array(ScaffoldFileSchema).min(1);
|
|
4565
|
-
var RepoRefSchema = external_exports.object({
|
|
4566
|
-
studioId: external_exports.string().uuid(),
|
|
4567
|
-
owner: external_exports.string().min(1),
|
|
4568
|
-
// GitHub org/account that owns the repo
|
|
4569
|
-
name: external_exports.string().min(1),
|
|
4570
|
-
fullName: external_exports.string().min(1),
|
|
4571
|
-
// owner/name
|
|
4572
|
-
htmlUrl: external_exports.string().url(),
|
|
4573
|
-
defaultBranch: external_exports.string().min(1).default("main")
|
|
4574
|
-
}).strict();
|
|
4575
|
-
var ScopedTokenSchema = external_exports.object({
|
|
4576
|
-
token: external_exports.string().min(1),
|
|
4577
|
-
expiresAt: external_exports.string(),
|
|
4578
|
-
// ISO-8601
|
|
4579
|
-
scope: external_exports.string().min(1)
|
|
4580
|
-
// human-readable, e.g. "contents:write on owner/name"
|
|
4581
|
-
}).strict();
|
|
4582
|
-
var BranchProtectionStatusSchema = external_exports.object({
|
|
4583
|
-
protected: external_exports.boolean(),
|
|
4584
|
-
requiresPullRequestReview: external_exports.boolean(),
|
|
4585
|
-
requiredApprovingReviewCount: external_exports.number().int().nonnegative(),
|
|
4586
|
-
allowsForcePushes: external_exports.boolean(),
|
|
4587
|
-
allowsDeletions: external_exports.boolean()
|
|
4588
|
-
}).strict();
|
|
4589
|
-
var RenderParamsSchema = external_exports.object({
|
|
4590
|
-
productName: external_exports.string().min(1),
|
|
4591
|
-
slug: external_exports.string().min(1),
|
|
4592
|
-
vertical: external_exports.string().min(1)
|
|
4593
|
-
}).strict();
|
|
4594
|
-
var TemplateInputFieldSchema = external_exports.object({
|
|
4595
|
-
name: external_exports.string().min(1),
|
|
4596
|
-
label: external_exports.string().min(1),
|
|
4597
|
-
inputType: external_exports.enum(["text", "number", "date", "slug"]),
|
|
4598
|
-
required: external_exports.boolean().default(true),
|
|
4599
|
-
helperText: external_exports.string().min(1),
|
|
4600
|
-
example: external_exports.string().min(1),
|
|
4601
|
-
defaultValue: external_exports.string().optional()
|
|
4602
|
-
}).strict();
|
|
4603
|
-
var TemplateInputSchema = external_exports.object({
|
|
4604
|
-
fields: external_exports.array(TemplateInputFieldSchema).min(1)
|
|
4605
|
-
}).strict();
|
|
4606
|
-
var TemplateDescriptorSchema = external_exports.object({
|
|
4607
|
-
templateRef: external_exports.string().min(1),
|
|
4608
|
-
vertical: external_exports.string().min(1),
|
|
4609
|
-
description: external_exports.string().default(""),
|
|
4610
|
-
inputSchema: TemplateInputSchema.optional()
|
|
4611
|
-
}).strict();
|
|
4612
|
-
var StandupDryRunPlanSchema = external_exports.object({
|
|
4613
|
-
planOnly: external_exports.literal(true),
|
|
4614
|
-
planOnlyMessage: external_exports.string().min(1),
|
|
4615
|
-
product: external_exports.object({
|
|
4616
|
-
studioId: external_exports.string().min(1),
|
|
4617
|
-
productId: external_exports.string().min(1),
|
|
4618
|
-
name: external_exports.string().min(1),
|
|
4619
|
-
slug: external_exports.string().min(1),
|
|
4620
|
-
vertical: external_exports.string().min(1)
|
|
4621
|
-
}).strict(),
|
|
4622
|
-
targetRepo: external_exports.object({
|
|
4623
|
-
owner: external_exports.string().min(1),
|
|
4624
|
-
name: external_exports.string().min(1),
|
|
4625
|
-
fullName: external_exports.string().min(1),
|
|
4626
|
-
defaultBranch: external_exports.string().min(1),
|
|
4627
|
-
plannedState: external_exports.literal("would_create"),
|
|
4628
|
-
exists: external_exports.literal(false)
|
|
4629
|
-
}).strict(),
|
|
4630
|
-
template: TemplateDescriptorSchema,
|
|
4631
|
-
scaffold: external_exports.object({
|
|
4632
|
-
label: external_exports.literal("scaffold (template output)"),
|
|
4633
|
-
files: ScaffoldManifestSchema
|
|
4634
|
-
}).strict(),
|
|
4635
|
-
buildAgentSeed: external_exports.object({
|
|
4636
|
-
label: external_exports.literal("build-agent instructions (not yet run)"),
|
|
4637
|
-
instructions: external_exports.array(external_exports.string().min(1)).min(1),
|
|
4638
|
-
product: external_exports.object({
|
|
4639
|
-
name: external_exports.string().min(1),
|
|
4640
|
-
slug: external_exports.string().min(1),
|
|
4641
|
-
vertical: external_exports.string().min(1)
|
|
4642
|
-
}).strict(),
|
|
4643
|
-
repoFullName: external_exports.string().min(1)
|
|
4644
|
-
}).strict(),
|
|
4645
|
-
safetyEnvelope: external_exports.object({
|
|
4646
|
-
estimatedCostUsd: external_exports.number().finite().nonnegative(),
|
|
4647
|
-
costCapUsd: external_exports.number().finite().nonnegative(),
|
|
4648
|
-
networkPolicy: external_exports.object({
|
|
4649
|
-
mode: external_exports.literal("restricted"),
|
|
4650
|
-
allowedHosts: external_exports.array(external_exports.string().min(1)).min(1)
|
|
4651
|
-
}).strict(),
|
|
4652
|
-
scopedToken: external_exports.object({
|
|
4653
|
-
tokenMinted: external_exports.literal(false),
|
|
4654
|
-
scope: external_exports.string().min(1),
|
|
4655
|
-
ttlSeconds: external_exports.number().int().positive()
|
|
4656
|
-
}).strict()
|
|
4657
|
-
}).strict()
|
|
4658
|
-
}).strict();
|
|
4659
|
-
var ConstructionWorkflowArtifactKindSchema = external_exports.enum([
|
|
4660
|
-
"profile",
|
|
4661
|
-
"milestone_schedule",
|
|
4662
|
-
"risk_register",
|
|
4663
|
-
"submittal_register",
|
|
4664
|
-
"long_lead_log",
|
|
4665
|
-
"rfi_log",
|
|
4666
|
-
"responsibility_matrix"
|
|
4667
|
-
]);
|
|
4668
|
-
var IsoDateSchema = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
4669
|
-
var ConstructionWorkflowTemplateDescriptorSchema = external_exports.object({
|
|
4670
|
-
templateRef: external_exports.string().min(1),
|
|
4671
|
-
workflowKind: external_exports.literal("construction_project"),
|
|
4672
|
-
templateKind: external_exports.literal("workflow_documents"),
|
|
4673
|
-
name: external_exports.string().min(1),
|
|
4674
|
-
description: external_exports.string().default(""),
|
|
4675
|
-
artifacts: external_exports.array(ConstructionWorkflowArtifactKindSchema).min(1),
|
|
4676
|
-
inputSchema: TemplateInputSchema
|
|
4677
|
-
}).strict();
|
|
4678
|
-
var ConstructionProjectSeedSchema = external_exports.object({
|
|
4679
|
-
projectName: external_exports.string().min(1).max(120),
|
|
4680
|
-
areaSqFt: external_exports.number().int().positive(),
|
|
4681
|
-
projectType: external_exports.string().min(1).max(120),
|
|
4682
|
-
buildingName: external_exports.string().min(1).max(160),
|
|
4683
|
-
ntpDate: IsoDateSchema,
|
|
4684
|
-
scheduleTargetDate: IsoDateSchema
|
|
4685
|
-
}).strict();
|
|
4686
|
-
var ConstructionMilestoneSchema = external_exports.object({
|
|
4687
|
-
id: external_exports.string().min(1),
|
|
4688
|
-
name: external_exports.string().min(1),
|
|
4689
|
-
targetDate: IsoDateSchema,
|
|
4690
|
-
status: external_exports.enum(["planned", "at_risk", "slipped", "complete"])
|
|
4691
|
-
}).strict();
|
|
4692
|
-
var ConstructionSubmittalSchema = external_exports.object({
|
|
4693
|
-
id: external_exports.string().min(1),
|
|
4694
|
-
item: external_exports.string().min(1),
|
|
4695
|
-
division: external_exports.string().min(1),
|
|
4696
|
-
needByDate: IsoDateSchema,
|
|
4697
|
-
status: external_exports.enum(["not_started", "open", "in_review", "approved", "done"])
|
|
4698
|
-
}).strict();
|
|
4699
|
-
var ConstructionRfiSchema = external_exports.object({
|
|
4700
|
-
id: external_exports.string().min(1),
|
|
4701
|
-
subject: external_exports.string().min(1),
|
|
4702
|
-
to: external_exports.string().min(1),
|
|
4703
|
-
status: external_exports.enum(["draft", "open", "answered", "closed"]),
|
|
4704
|
-
openedDate: IsoDateSchema
|
|
4705
|
-
}).strict();
|
|
4706
|
-
var ConstructionRiskSchema = external_exports.object({
|
|
4707
|
-
id: external_exports.string().min(1),
|
|
4708
|
-
risk: external_exports.string().min(1),
|
|
4709
|
-
rating: external_exports.enum(["low", "medium", "high"]),
|
|
4710
|
-
mitigation: external_exports.string().min(1),
|
|
4711
|
-
confidence: external_exports.number().min(0).max(1)
|
|
4712
|
-
}).strict();
|
|
4713
|
-
var ConstructionLongLeadItemSchema = external_exports.object({
|
|
4714
|
-
id: external_exports.string().min(1),
|
|
4715
|
-
item: external_exports.string().min(1),
|
|
4716
|
-
needByDate: IsoDateSchema,
|
|
4717
|
-
status: external_exports.enum(["tracking", "ordered", "received", "done"]),
|
|
4718
|
-
assumption: external_exports.string().min(1)
|
|
4719
|
-
}).strict();
|
|
4720
|
-
var ConstructionResponsibilitySchema = external_exports.object({
|
|
4721
|
-
id: external_exports.string().min(1),
|
|
4722
|
-
role: external_exports.string().min(1),
|
|
4723
|
-
owner: external_exports.string().min(1),
|
|
4724
|
-
responsibility: external_exports.string().min(1)
|
|
4725
|
-
}).strict();
|
|
4726
|
-
var ConstructionMarkdownArtifactSchema = external_exports.object({
|
|
4727
|
-
kind: ConstructionWorkflowArtifactKindSchema,
|
|
4728
|
-
path: external_exports.string().min(1),
|
|
4729
|
-
markdown: external_exports.string().min(1)
|
|
4730
|
-
}).strict();
|
|
4731
|
-
var ConstructionWorkflowArtifactSetSchema = external_exports.object({
|
|
4732
|
-
projectName: external_exports.string().min(1),
|
|
4733
|
-
generatedAt: external_exports.string().datetime(),
|
|
4734
|
-
assumptions: external_exports.array(external_exports.string().min(1)).default([]),
|
|
4735
|
-
needsPmData: external_exports.array(external_exports.string().min(1)).default([]),
|
|
4736
|
-
markdownArtifacts: external_exports.array(ConstructionMarkdownArtifactSchema).min(1),
|
|
4737
|
-
structured: external_exports.object({
|
|
4738
|
-
milestones: external_exports.array(ConstructionMilestoneSchema),
|
|
4739
|
-
submittals: external_exports.array(ConstructionSubmittalSchema),
|
|
4740
|
-
rfis: external_exports.array(ConstructionRfiSchema),
|
|
4741
|
-
risks: external_exports.array(ConstructionRiskSchema),
|
|
4742
|
-
longLeadItems: external_exports.array(ConstructionLongLeadItemSchema),
|
|
4743
|
-
responsibilities: external_exports.array(ConstructionResponsibilitySchema)
|
|
4744
|
-
}).strict()
|
|
4745
|
-
}).strict();
|
|
4746
|
-
var ConstructionWorkflowDryRunPlanSchema = external_exports.object({
|
|
4747
|
-
planOnly: external_exports.literal(true),
|
|
4748
|
-
planOnlyMessage: external_exports.string().min(1),
|
|
4749
|
-
product: external_exports.object({
|
|
4750
|
-
studioId: external_exports.string().min(1),
|
|
4751
|
-
productId: external_exports.string().min(1),
|
|
4752
|
-
name: external_exports.string().min(1),
|
|
4753
|
-
vertical: external_exports.string().min(1)
|
|
4754
|
-
}).strict(),
|
|
4755
|
-
template: ConstructionWorkflowTemplateDescriptorSchema,
|
|
4756
|
-
seed: ConstructionProjectSeedSchema,
|
|
4757
|
-
safetyEnvelope: external_exports.object({
|
|
4758
|
-
executor: external_exports.literal("benign_workflow_populator"),
|
|
4759
|
-
sandboxUsed: external_exports.literal(false),
|
|
4760
|
-
scopedTokenMinted: external_exports.literal(false),
|
|
4761
|
-
externalWritesAllowed: external_exports.literal(false),
|
|
4762
|
-
workspaceWriteMode: external_exports.literal("markdown_only")
|
|
4763
|
-
}).strict()
|
|
4764
|
-
}).strict();
|
|
4765
|
-
|
|
4766
|
-
// ../shared/src/types/construction-log-excel.ts
|
|
4767
|
-
var CONSTRUCTION_LOG_EXCEL_SCHEMA_VERSION = "construction-log-excel-v1";
|
|
4768
|
-
var ConstructionLogExcelSheetKeySchema = external_exports.enum([
|
|
4769
|
-
"submittals",
|
|
4770
|
-
"rfis",
|
|
4771
|
-
"riskRegister",
|
|
4772
|
-
"longLead",
|
|
4773
|
-
"responsibilityMatrix",
|
|
4774
|
-
"milestones"
|
|
4775
|
-
]);
|
|
4776
|
-
var ConstructionLogExcelColumnSchema = external_exports.object({
|
|
4777
|
-
key: external_exports.string().min(1),
|
|
4778
|
-
header: external_exports.string().min(1),
|
|
4779
|
-
required: external_exports.boolean(),
|
|
4780
|
-
description: external_exports.string().min(1)
|
|
4781
|
-
}).strict().describe("Canonical column definition for Alfred construction log Excel round-trips.");
|
|
4782
|
-
var ConstructionLogExcelSheetSchema = external_exports.object({
|
|
4783
|
-
key: ConstructionLogExcelSheetKeySchema,
|
|
4784
|
-
sheetName: external_exports.string().min(1),
|
|
4785
|
-
description: external_exports.string().min(1),
|
|
4786
|
-
columns: external_exports.array(ConstructionLogExcelColumnSchema).min(1)
|
|
4787
|
-
}).strict().describe("Canonical worksheet definition for Alfred construction log Excel round-trips.");
|
|
4788
|
-
var ConstructionLogExcelWorkbookSchema = external_exports.object({
|
|
4789
|
-
schemaVersion: external_exports.literal(CONSTRUCTION_LOG_EXCEL_SCHEMA_VERSION),
|
|
4790
|
-
sheets: external_exports.record(ConstructionLogExcelSheetKeySchema, ConstructionLogExcelSheetSchema)
|
|
4791
|
-
}).strict().describe(
|
|
4792
|
-
"Canonical Alfred construction log Excel workbook schema shared by native output generation and export-upload ingestion."
|
|
4793
|
-
);
|
|
4794
|
-
var CONSTRUCTION_LOG_EXCEL_SHEETS = {
|
|
4795
|
-
submittals: {
|
|
4796
|
-
key: "submittals",
|
|
4797
|
-
sheetName: "Submittals",
|
|
4798
|
-
description: "Submittal register rows generated by Alfred or edited by the PM.",
|
|
4799
|
-
columns: [
|
|
4800
|
-
column("id", "ID", true, "Stable submittal identifier, for example SUB-001."),
|
|
4801
|
-
column("item", "Item", true, "Submittal item or package name."),
|
|
4802
|
-
column("division", "Division", true, "Spec division or trade grouping."),
|
|
4803
|
-
column("needByDate", "Need By Date", true, "Date needed in YYYY-MM-DD format."),
|
|
4804
|
-
column("status", "Status", true, "One of not_started, open, in_review, approved, or done."),
|
|
4805
|
-
commonColumn("assumptionsNotes")
|
|
4806
|
-
]
|
|
4807
|
-
},
|
|
4808
|
-
rfis: {
|
|
4809
|
-
key: "rfis",
|
|
4810
|
-
sheetName: "RFIs",
|
|
4811
|
-
description: "RFI log rows generated by Alfred or edited by the PM.",
|
|
4812
|
-
columns: [
|
|
4813
|
-
column("id", "ID", true, "Stable RFI identifier, for example RFI-001."),
|
|
4814
|
-
column("subject", "Subject", true, "RFI subject."),
|
|
4815
|
-
column("to", "To", true, "Responsible recipient or ball-in-court party."),
|
|
4816
|
-
column("status", "Status", true, "One of draft, open, answered, or closed."),
|
|
4817
|
-
column("openedDate", "Opened Date", true, "Date opened in YYYY-MM-DD format."),
|
|
4818
|
-
commonColumn("assumptionsNotes")
|
|
4819
|
-
]
|
|
4820
|
-
},
|
|
4821
|
-
riskRegister: {
|
|
4822
|
-
key: "riskRegister",
|
|
4823
|
-
sheetName: "Risk Register",
|
|
4824
|
-
description: "Risk register rows generated by Alfred or edited by the PM.",
|
|
4825
|
-
columns: [
|
|
4826
|
-
column("id", "ID", true, "Stable risk identifier, for example RISK-001."),
|
|
4827
|
-
column("risk", "Risk", true, "Risk statement."),
|
|
4828
|
-
column("rating", "Rating", true, "One of low, medium, or high."),
|
|
4829
|
-
column("mitigation", "Mitigation", true, "Mitigation plan."),
|
|
4830
|
-
column("confidence", "Confidence", true, "Confidence score from 0 to 1."),
|
|
4831
|
-
commonColumn("assumptionsNotes")
|
|
4832
|
-
]
|
|
4833
|
-
},
|
|
4834
|
-
longLead: {
|
|
4835
|
-
key: "longLead",
|
|
4836
|
-
sheetName: "Long-Lead",
|
|
4837
|
-
description: "Long-lead procurement rows generated by Alfred or edited by the PM.",
|
|
4838
|
-
columns: [
|
|
4839
|
-
column("id", "ID", true, "Stable long-lead identifier, for example LL-001."),
|
|
4840
|
-
column("item", "Item", true, "Long-lead item name."),
|
|
4841
|
-
column("needByDate", "Need By Date", true, "Date needed in YYYY-MM-DD format."),
|
|
4842
|
-
column("status", "Status", true, "One of tracking, ordered, received, or done."),
|
|
4843
|
-
column("assumption", "Assumption", true, "Procurement assumption behind this row."),
|
|
4844
|
-
commonColumn("assumptionsNotes")
|
|
4845
|
-
]
|
|
4846
|
-
},
|
|
4847
|
-
responsibilityMatrix: {
|
|
4848
|
-
key: "responsibilityMatrix",
|
|
4849
|
-
sheetName: "Responsibility Matrix",
|
|
4850
|
-
description: "Responsibility matrix rows generated by Alfred or edited by the PM.",
|
|
4851
|
-
columns: [
|
|
4852
|
-
column("id", "ID", true, "Stable responsibility identifier, for example RESP-001."),
|
|
4853
|
-
column("role", "Role", true, "Role or party."),
|
|
4854
|
-
column("owner", "Owner", true, "Named owner, or Needs PM input when unknown."),
|
|
4855
|
-
column("responsibility", "Responsibility", true, "Responsibility statement."),
|
|
4856
|
-
commonColumn("assumptionsNotes")
|
|
4857
|
-
]
|
|
4858
|
-
},
|
|
4859
|
-
milestones: {
|
|
4860
|
-
key: "milestones",
|
|
4861
|
-
sheetName: "Milestones",
|
|
4862
|
-
description: "Milestone schedule rows used to generate the MS Project XML schedule.",
|
|
4863
|
-
columns: [
|
|
4864
|
-
column("id", "ID", true, "Stable milestone identifier, for example MS-001."),
|
|
4865
|
-
column("name", "Name", true, "Milestone or task name."),
|
|
4866
|
-
column("targetDate", "Target Date", true, "Target date in YYYY-MM-DD format."),
|
|
4867
|
-
column("status", "Status", true, "One of planned, at_risk, slipped, or complete."),
|
|
4868
|
-
column("predecessorId", "Predecessor ID", false, "Optional predecessor milestone ID."),
|
|
4869
|
-
commonColumn("assumptionsNotes")
|
|
4870
|
-
]
|
|
4871
|
-
}
|
|
4872
|
-
};
|
|
4873
|
-
var CONSTRUCTION_LOG_EXCEL_WORKBOOK_SCHEMA = ConstructionLogExcelWorkbookSchema.parse({
|
|
4874
|
-
schemaVersion: CONSTRUCTION_LOG_EXCEL_SCHEMA_VERSION,
|
|
4875
|
-
sheets: CONSTRUCTION_LOG_EXCEL_SHEETS
|
|
4876
|
-
});
|
|
4877
|
-
function column(key, header, required, description) {
|
|
4878
|
-
return { key, header, required, description };
|
|
4879
|
-
}
|
|
4880
|
-
function commonColumn(key) {
|
|
4881
|
-
return column(
|
|
4882
|
-
key,
|
|
4883
|
-
"Assumptions / Notes",
|
|
4884
|
-
false,
|
|
4885
|
-
"Show-your-work note, including generated assumptions and PM-input gaps."
|
|
4886
|
-
);
|
|
4887
|
-
}
|
|
4888
|
-
|
|
4889
|
-
// ../shared/src/types/dev-task-dispatch.ts
|
|
4890
|
-
var CodingAgentExecutorSchema = external_exports.enum(["claude-code", "codex"]);
|
|
4891
|
-
var DevTaskDispatchRequestSchema = external_exports.object({
|
|
4892
|
-
studioId: external_exports.string().uuid(),
|
|
4893
|
-
productId: external_exports.string().uuid(),
|
|
4894
|
-
repo: RepoRefSchema,
|
|
4895
|
-
task: external_exports.string().min(1).max(2e4),
|
|
4896
|
-
executor: CodingAgentExecutorSchema
|
|
4897
|
-
}).strict();
|
|
4898
|
-
var DevTaskDispatchDryRunPlanSchema = external_exports.object({
|
|
4899
|
-
planOnly: external_exports.literal(true),
|
|
4900
|
-
planOnlyMessage: external_exports.string().min(1),
|
|
4901
|
-
targetRepo: RepoRefSchema,
|
|
4902
|
-
task: external_exports.string().min(1),
|
|
4903
|
-
executor: CodingAgentExecutorSchema,
|
|
4904
|
-
branchName: external_exports.string().min(1),
|
|
4905
|
-
safetyEnvelope: external_exports.object({
|
|
4906
|
-
estimatedCostUsd: external_exports.number().finite().nonnegative(),
|
|
4907
|
-
costCapUsd: external_exports.number().finite().nonnegative(),
|
|
4908
|
-
timeoutMs: external_exports.number().int().positive(),
|
|
4909
|
-
scopedToken: external_exports.object({
|
|
4910
|
-
tokenMinted: external_exports.literal(false),
|
|
4911
|
-
scope: external_exports.string().min(1),
|
|
4912
|
-
ttlSeconds: external_exports.number().int().positive()
|
|
4913
|
-
}).strict(),
|
|
4914
|
-
prOnly: external_exports.object({
|
|
4915
|
-
opensPullRequest: external_exports.literal(true),
|
|
4916
|
-
mergesPullRequest: external_exports.literal(false),
|
|
4917
|
-
pushesMain: external_exports.literal(false),
|
|
4918
|
-
deploys: external_exports.literal(false)
|
|
4919
|
-
}).strict()
|
|
4920
|
-
}).strict()
|
|
4921
|
-
}).strict();
|
|
4922
|
-
var CodingAgentRunInputSchema = external_exports.object({
|
|
4923
|
-
executor: CodingAgentExecutorSchema,
|
|
4924
|
-
repo: RepoRefSchema,
|
|
4925
|
-
task: external_exports.string().min(1),
|
|
4926
|
-
scopedToken: ScopedTokenSchema,
|
|
4927
|
-
branchName: external_exports.string().min(1),
|
|
4928
|
-
costCapUsd: external_exports.number().finite().nonnegative(),
|
|
4929
|
-
timeoutMs: external_exports.number().int().positive()
|
|
4930
|
-
}).strict();
|
|
4931
|
-
var CodingAgentRunResultSchema = external_exports.discriminatedUnion("status", [
|
|
4932
|
-
external_exports.object({
|
|
4933
|
-
status: external_exports.literal("succeeded"),
|
|
4934
|
-
prUrl: external_exports.string().url(),
|
|
4935
|
-
summary: external_exports.string().min(1),
|
|
4936
|
-
costUsd: external_exports.number().finite().nonnegative(),
|
|
4937
|
-
/**
|
|
4938
|
-
* The exact commit sha the PR branch was pushed at when it opened —
|
|
4939
|
-
* captured server-side (see server-dispatch-backend.ts) right after a
|
|
4940
|
-
* successful run, before the workspace is torn down. Lets the Maeve
|
|
4941
|
-
* in-flight-fix detector (maeve-in-flight-pr-fix-lesson.ts) key off the
|
|
4942
|
-
* real PR-open head instead of falling back to timestamp matching.
|
|
4943
|
-
*/
|
|
4944
|
-
openedHeadSha: external_exports.string().min(1).optional()
|
|
4945
|
-
}).strict(),
|
|
4946
|
-
external_exports.object({
|
|
4947
|
-
status: external_exports.literal("failed"),
|
|
4948
|
-
summary: external_exports.string().min(1),
|
|
4949
|
-
reason: external_exports.string().min(1),
|
|
4950
|
-
costUsd: external_exports.number().finite().nonnegative().optional()
|
|
4951
|
-
}).strict()
|
|
4952
|
-
]);
|
|
4953
|
-
var DevTaskOutcomeSchema = external_exports.enum(["ci_passed", "pr_merged", "ci_failed"]);
|
|
4954
|
-
var SecurityFindingClassSchema = external_exports.enum(["authz", "csrf", "injection", "secrets", "ssrf"]);
|
|
4955
|
-
var RecordDevTaskOutcomeInputSchema = external_exports.object({
|
|
4956
|
-
product: external_exports.string().min(1).max(120),
|
|
4957
|
-
repo: external_exports.string().min(1).max(240),
|
|
4958
|
-
prUrl: external_exports.string().url(),
|
|
4959
|
-
outcome: DevTaskOutcomeSchema,
|
|
4960
|
-
task: external_exports.string().min(1).max(2e4).optional(),
|
|
4961
|
-
executor: CodingAgentExecutorSchema.optional(),
|
|
4962
|
-
occurredAt: external_exports.string().datetime().optional(),
|
|
4963
|
-
maeveLessonStatement: external_exports.string().min(1).max(1e3).optional(),
|
|
4964
|
-
maeveLessonTags: external_exports.array(external_exports.string().min(1).max(120)).optional(),
|
|
4965
|
-
/** Security metadata — enriches the Maeve lesson with class/pattern, never raw vulnerable detail. */
|
|
4966
|
-
findingClass: SecurityFindingClassSchema.optional(),
|
|
4967
|
-
ruleId: external_exports.string().min(1).max(120).optional(),
|
|
4968
|
-
signalSource: external_exports.string().min(1).max(240).optional()
|
|
4969
|
-
}).strict();
|
|
4970
|
-
|
|
4971
|
-
// ../shared/src/schemas/standup-plan.ts
|
|
4972
|
-
var StandupRequestSchema = external_exports.object({
|
|
4973
|
-
productName: external_exports.string().min(1).max(80),
|
|
4974
|
-
slug: external_exports.string().min(1).optional(),
|
|
4975
|
-
vertical: external_exports.string().min(1).max(80),
|
|
4976
|
-
repoTarget: external_exports.string().min(1).default("barg-labs"),
|
|
4977
|
-
repoName: external_exports.string().min(1).optional(),
|
|
4978
|
-
templateRef: external_exports.string().min(1).optional(),
|
|
4979
|
-
scopeNotes: external_exports.string().max(2e3).optional()
|
|
4980
|
-
}).strict();
|
|
4981
|
-
var StandupPlanSchema = external_exports.object({
|
|
4982
|
-
productName: external_exports.string().min(1).max(80),
|
|
4983
|
-
slug: external_exports.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/),
|
|
4984
|
-
vertical: external_exports.string().min(1).max(80),
|
|
4985
|
-
templateRef: external_exports.string().min(1),
|
|
4986
|
-
repoTarget: external_exports.string().min(1),
|
|
4987
|
-
repoName: external_exports.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/),
|
|
4988
|
-
fileManifest: external_exports.array(external_exports.string().min(1)).min(1),
|
|
4989
|
-
credentialScope: external_exports.string().min(1),
|
|
4990
|
-
estimatedCostUsd: external_exports.number().nonnegative(),
|
|
4991
|
-
steps: external_exports.array(external_exports.string().min(1)).min(1),
|
|
4992
|
-
dryRun: external_exports.literal(true)
|
|
4993
|
-
}).strict();
|
|
4994
|
-
|
|
4995
|
-
// ../shared/src/types/coordinator-prompt.ts
|
|
4996
|
-
var CoordinatorPromptContextBlockSchema = external_exports.object({
|
|
4997
|
-
title: external_exports.string().min(1).max(120),
|
|
4998
|
-
body: external_exports.string().min(1).max(6e3),
|
|
4999
|
-
source: external_exports.string().max(500).optional()
|
|
5000
|
-
});
|
|
5001
|
-
var CoordinatorPromptInputPayloadSchema = external_exports.object({
|
|
5002
|
-
objective: external_exports.string().min(1).max(4e3),
|
|
5003
|
-
productId: external_exports.string().min(1),
|
|
5004
|
-
context: external_exports.array(CoordinatorPromptContextBlockSchema).min(1).max(20),
|
|
5005
|
-
escalationHints: external_exports.array(external_exports.string().min(1).max(500)).max(10).optional()
|
|
5006
|
-
});
|
|
5007
|
-
var CoordinatorPromptTokensUsedSchema = external_exports.object({
|
|
5008
|
-
input: external_exports.number().int().nonnegative(),
|
|
5009
|
-
output: external_exports.number().int().nonnegative(),
|
|
5010
|
-
total: external_exports.number().int().nonnegative(),
|
|
5011
|
-
costCents: external_exports.number().nonnegative()
|
|
5012
|
-
});
|
|
5013
|
-
var CoordinatorPromptSchema = external_exports.object({
|
|
5014
|
-
id: external_exports.string().uuid(),
|
|
5015
|
-
studioId: external_exports.string().min(1),
|
|
5016
|
-
productId: external_exports.string().min(1),
|
|
5017
|
-
draftedAt: external_exports.coerce.date(),
|
|
5018
|
-
inputPayload: CoordinatorPromptInputPayloadSchema,
|
|
5019
|
-
markdown: external_exports.string().min(1),
|
|
5020
|
-
metadata: external_exports.object({
|
|
5021
|
-
tokensUsed: CoordinatorPromptTokensUsedSchema.optional(),
|
|
5022
|
-
model: external_exports.string().optional(),
|
|
5023
|
-
templateVersion: external_exports.string().optional()
|
|
5024
|
-
}).catchall(external_exports.unknown()).optional()
|
|
5025
|
-
});
|
|
5026
|
-
var CreateCoordinatorPromptInputSchema = external_exports.object({
|
|
5027
|
-
productId: external_exports.string().min(1),
|
|
5028
|
-
inputPayload: CoordinatorPromptInputPayloadSchema,
|
|
5029
|
-
markdown: external_exports.string().min(1),
|
|
5030
|
-
metadata: external_exports.record(external_exports.unknown()).optional(),
|
|
5031
|
-
draftedAt: external_exports.coerce.date().optional()
|
|
5032
|
-
});
|
|
5033
|
-
var ListCoordinatorPromptsInputSchema = external_exports.object({
|
|
5034
|
-
productId: external_exports.string().min(1).optional(),
|
|
5035
|
-
since: external_exports.coerce.date().optional()
|
|
5036
|
-
});
|
|
5037
|
-
|
|
5038
|
-
// ../shared/src/schemas/inbox-triage.ts
|
|
5039
|
-
var InboxTriageClassificationSchema = external_exports.enum([
|
|
5040
|
-
"needs_reply",
|
|
5041
|
-
"fyi",
|
|
5042
|
-
"waiting",
|
|
5043
|
-
"escalate"
|
|
5044
|
-
]);
|
|
5045
|
-
var InboxTriageLegacyUrgencySchema = external_exports.enum(["needs_reply", "fyi", "noise", "escalation"]);
|
|
5046
|
-
var InboxTriageThreadSchema = external_exports.object({
|
|
5047
|
-
id: external_exports.string().min(1),
|
|
5048
|
-
subject: external_exports.string().min(1),
|
|
5049
|
-
from: external_exports.string(),
|
|
5050
|
-
to: external_exports.string(),
|
|
5051
|
-
snippet: external_exports.string(),
|
|
5052
|
-
labels: external_exports.array(external_exports.string()),
|
|
5053
|
-
unread: external_exports.boolean(),
|
|
5054
|
-
needsReply: external_exports.boolean(),
|
|
5055
|
-
updatedAt: external_exports.string().min(1),
|
|
5056
|
-
url: external_exports.string().min(1),
|
|
5057
|
-
messageCount: external_exports.number().int().nonnegative()
|
|
5058
|
-
});
|
|
5059
|
-
var InboxTriageResultSchema = external_exports.object({
|
|
5060
|
-
threadId: external_exports.string().min(1),
|
|
5061
|
-
classification: InboxTriageClassificationSchema,
|
|
5062
|
-
confidence: external_exports.number().min(0).max(1),
|
|
5063
|
-
reason: external_exports.string(),
|
|
5064
|
-
labelName: external_exports.string(),
|
|
5065
|
-
applied: external_exports.boolean(),
|
|
5066
|
-
error: external_exports.string().optional()
|
|
5067
|
-
});
|
|
5068
|
-
var TriageInboxUsageSchema = external_exports.object({
|
|
5069
|
-
input_tokens: external_exports.number().int().nonnegative(),
|
|
5070
|
-
output_tokens: external_exports.number().int().nonnegative(),
|
|
5071
|
-
cached_tokens: external_exports.number().int().nonnegative().optional(),
|
|
5072
|
-
cost_cents: external_exports.number().nonnegative()
|
|
5073
|
-
});
|
|
5074
|
-
var TriageInboxResultSchema = external_exports.object({
|
|
5075
|
-
productId: external_exports.string().min(1),
|
|
5076
|
-
results: external_exports.array(InboxTriageResultSchema),
|
|
5077
|
-
usage: TriageInboxUsageSchema.optional()
|
|
5078
|
-
});
|
|
5079
|
-
|
|
5080
|
-
// ../shared/src/schemas/inference-usage.ts
|
|
5081
|
-
var InferenceUsageSurfaceSchema = external_exports.string().min(1).max(80).regex(/^[a-z][a-z0-9_-]*$/);
|
|
5082
|
-
var RecordInferenceUsageInputSchema = external_exports.object({
|
|
5083
|
-
product: external_exports.string().min(1).optional(),
|
|
5084
|
-
surface: InferenceUsageSurfaceSchema,
|
|
5085
|
-
model: external_exports.string().min(1).max(120),
|
|
5086
|
-
inputTokens: external_exports.number().int().nonnegative(),
|
|
5087
|
-
outputTokens: external_exports.number().int().nonnegative(),
|
|
5088
|
-
cachedTokens: external_exports.number().int().nonnegative().default(0),
|
|
5089
|
-
costCents: external_exports.number().nonnegative(),
|
|
5090
|
-
timestamp: external_exports.coerce.date().optional()
|
|
5091
|
-
});
|
|
5092
|
-
var InferenceUsageBreakdownQuerySchema = external_exports.object({
|
|
5093
|
-
from: external_exports.coerce.date(),
|
|
5094
|
-
to: external_exports.coerce.date()
|
|
5095
|
-
});
|
|
5096
|
-
var InferenceUsageGroupSchema = external_exports.object({
|
|
5097
|
-
calls: external_exports.number().int().nonnegative(),
|
|
5098
|
-
costCents: external_exports.number().nonnegative(),
|
|
5099
|
-
inputTokens: external_exports.number().int().nonnegative(),
|
|
5100
|
-
outputTokens: external_exports.number().int().nonnegative(),
|
|
5101
|
-
cachedTokens: external_exports.number().int().nonnegative()
|
|
5102
|
-
});
|
|
5103
|
-
var InferenceUsageBreakdownSchema = external_exports.object({
|
|
5104
|
-
from: external_exports.string().datetime(),
|
|
5105
|
-
to: external_exports.string().datetime(),
|
|
5106
|
-
totals: InferenceUsageGroupSchema,
|
|
5107
|
-
bySurface: external_exports.array(InferenceUsageGroupSchema.extend({ surface: InferenceUsageSurfaceSchema })),
|
|
5108
|
-
byModel: external_exports.array(InferenceUsageGroupSchema.extend({ model: external_exports.string().min(1) }))
|
|
5109
|
-
});
|
|
5110
|
-
|
|
5111
|
-
// ../shared/src/schemas/product-health.ts
|
|
5112
|
-
var DEFAULT_PRODUCT_HEALTH_INTERVAL_SECONDS = 24 * 60 * 60;
|
|
5113
|
-
var ISO_DATE_STRING = external_exports.string().datetime({ offset: true }).describe("ISO-8601 timestamp with timezone offset.");
|
|
5114
|
-
var ProductHealthStatusSchema = external_exports.enum(["healthy", "degraded", "halted"]);
|
|
5115
|
-
var ProductHealthDetailsSchema = external_exports.record(external_exports.unknown()).superRefine((details, ctx) => {
|
|
5116
|
-
const credentialPath = findCredentialLikePath(details);
|
|
5117
|
-
if (!credentialPath) return;
|
|
5118
|
-
ctx.addIssue({
|
|
5119
|
-
code: external_exports.ZodIssueCode.custom,
|
|
5120
|
-
message: `Product health details must not contain credentials (${credentialPath}).`
|
|
5121
|
-
});
|
|
5122
|
-
});
|
|
5123
|
-
var ProductHealthReportInputSchema = external_exports.object({
|
|
5124
|
-
productId: external_exports.string().min(1).max(120),
|
|
5125
|
-
status: ProductHealthStatusSchema,
|
|
5126
|
-
lastActivityAt: ISO_DATE_STRING,
|
|
5127
|
-
summary: external_exports.string().min(1).max(1e3),
|
|
5128
|
-
details: ProductHealthDetailsSchema.optional(),
|
|
5129
|
-
reportedAt: ISO_DATE_STRING,
|
|
5130
|
-
expectedIntervalSeconds: external_exports.number().int().positive().optional()
|
|
5131
|
-
});
|
|
5132
|
-
var StoredProductHealthReportSchema = ProductHealthReportInputSchema.extend({
|
|
5133
|
-
expectedIntervalSeconds: external_exports.number().int().positive()
|
|
5134
|
-
});
|
|
5135
|
-
var ProductLivenessStateSchema = external_exports.enum([
|
|
5136
|
-
"healthy",
|
|
5137
|
-
"degraded",
|
|
5138
|
-
"halted",
|
|
5139
|
-
"stale",
|
|
5140
|
-
"unknown"
|
|
5141
|
-
]);
|
|
5142
|
-
var ProductLivenessSnapshotEntrySchema = external_exports.object({
|
|
5143
|
-
productId: external_exports.string().min(1),
|
|
5144
|
-
state: ProductLivenessStateSchema,
|
|
5145
|
-
flagged: external_exports.boolean(),
|
|
5146
|
-
status: ProductHealthStatusSchema.optional(),
|
|
5147
|
-
lastActivityAt: ISO_DATE_STRING.optional(),
|
|
5148
|
-
reportedAt: ISO_DATE_STRING.optional(),
|
|
5149
|
-
expectedIntervalSeconds: external_exports.number().int().positive(),
|
|
5150
|
-
ageSeconds: external_exports.number().int().nonnegative().nullable(),
|
|
5151
|
-
summary: external_exports.string()
|
|
5152
|
-
});
|
|
5153
|
-
function findCredentialLikePath(value, path = []) {
|
|
5154
|
-
if (!value || typeof value !== "object") return null;
|
|
5155
|
-
if (Array.isArray(value)) {
|
|
5156
|
-
for (const [index, item] of value.entries()) {
|
|
5157
|
-
const match = findCredentialLikePath(item, [...path, String(index)]);
|
|
5158
|
-
if (match) return match;
|
|
5159
|
-
}
|
|
5160
|
-
return null;
|
|
5161
|
-
}
|
|
5162
|
-
for (const [key, nested] of Object.entries(value)) {
|
|
5163
|
-
const nextPath = [...path, key];
|
|
5164
|
-
if (/(?:secret|token|password|credential|api[-_]?key|private[-_]?key)/i.test(key)) {
|
|
5165
|
-
return nextPath.join(".");
|
|
5166
|
-
}
|
|
5167
|
-
const match = findCredentialLikePath(nested, nextPath);
|
|
5168
|
-
if (match) return match;
|
|
5169
|
-
}
|
|
5170
|
-
return null;
|
|
5171
|
-
}
|
|
5172
|
-
|
|
5173
|
-
// ../shared/src/schemas/interaction-trace.ts
|
|
5174
|
-
var InteractionTraceVerificationSignalSchema = external_exports.enum([
|
|
5175
|
-
"no_signal",
|
|
5176
|
-
"human_accepted_output",
|
|
5177
|
-
"human_rejected_output",
|
|
5178
|
-
"ci_pr_succeeded",
|
|
5179
|
-
"ci_pr_failed",
|
|
5180
|
-
"brief_accepted",
|
|
5181
|
-
"brief_rejected",
|
|
5182
|
-
"standup_completed",
|
|
5183
|
-
"standup_failed"
|
|
5184
|
-
]);
|
|
5185
|
-
var InteractionTraceVerificationSchema = external_exports.object({
|
|
5186
|
-
success: external_exports.boolean(),
|
|
5187
|
-
signal: InteractionTraceVerificationSignalSchema,
|
|
5188
|
-
confidence: external_exports.number().min(0).max(1),
|
|
5189
|
-
reason: external_exports.string().min(1).max(1e3)
|
|
5190
|
-
});
|
|
5191
|
-
var InteractionTraceActorSchema = external_exports.object({
|
|
5192
|
-
type: external_exports.enum(["human", "agent", "system"]),
|
|
5193
|
-
id: external_exports.string().min(1).max(200),
|
|
5194
|
-
name: external_exports.string().min(1).max(200).optional()
|
|
5195
|
-
});
|
|
5196
|
-
var RecordInteractionTraceInputSchema = external_exports.object({
|
|
5197
|
-
product: external_exports.string().min(1).max(120),
|
|
5198
|
-
intent: external_exports.string().min(1).max(500),
|
|
5199
|
-
actionSummary: external_exports.string().min(1).max(4e3),
|
|
5200
|
-
outcomeSummary: external_exports.string().min(1).max(4e3),
|
|
5201
|
-
model: external_exports.string().min(1).max(200).nullable().optional(),
|
|
5202
|
-
actor: InteractionTraceActorSchema,
|
|
5203
|
-
occurredAt: external_exports.string().datetime().optional(),
|
|
5204
|
-
verification: InteractionTraceVerificationSchema.optional(),
|
|
5205
|
-
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
5206
|
-
});
|
|
5207
|
-
var StoredInteractionTraceSchema = RecordInteractionTraceInputSchema.extend({
|
|
5208
|
-
id: external_exports.string().uuid(),
|
|
5209
|
-
occurredAt: external_exports.string().datetime(),
|
|
5210
|
-
createdAt: external_exports.string().datetime(),
|
|
5211
|
-
verification: InteractionTraceVerificationSchema
|
|
5212
|
-
});
|
|
5213
|
-
var InteractionTraceQualityScoreSchema = external_exports.number().min(0).max(1);
|
|
5214
|
-
var RetrieveRelevantTracesQuerySchema = external_exports.object({
|
|
5215
|
-
product: external_exports.string().min(1).max(120),
|
|
5216
|
-
intent: external_exports.string().min(1).max(500),
|
|
5217
|
-
limit: external_exports.number().int().positive().max(10).optional()
|
|
5218
|
-
});
|
|
5219
|
-
var RetrievedInteractionTraceSchema = StoredInteractionTraceSchema.extend({
|
|
5220
|
-
score: external_exports.number().min(0).max(1),
|
|
5221
|
-
qualityScore: InteractionTraceQualityScoreSchema
|
|
5222
|
-
});
|
|
5223
|
-
|
|
5224
|
-
// ../shared/src/schemas/maeve-lesson.ts
|
|
5225
|
-
var MaeveLessonStatusSchema = external_exports.enum(["candidate", "verified", "retired"]);
|
|
5226
|
-
var MaeveLessonEvidenceSchema = external_exports.object({
|
|
5227
|
-
source: external_exports.enum(["interaction_trace", "artifact"]),
|
|
5228
|
-
traceId: external_exports.string().uuid().optional(),
|
|
5229
|
-
artifact: external_exports.string().min(1).max(1e3).optional(),
|
|
5230
|
-
summary: external_exports.string().min(1).max(1e3),
|
|
5231
|
-
hash: external_exports.string().regex(/^sha256:[a-f0-9]{64}$/)
|
|
5232
|
-
});
|
|
5233
|
-
var MaeveLessonSchema = external_exports.object({
|
|
5234
|
-
id: external_exports.string().uuid(),
|
|
5235
|
-
product: external_exports.string().min(1).max(120),
|
|
5236
|
-
statement: external_exports.string().min(1).max(1e3),
|
|
5237
|
-
scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5238
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5239
|
-
evidence: external_exports.array(MaeveLessonEvidenceSchema),
|
|
5240
|
-
status: MaeveLessonStatusSchema,
|
|
5241
|
-
createdAt: external_exports.string().datetime(),
|
|
5242
|
-
lastSeenAt: external_exports.string().datetime()
|
|
5243
|
-
});
|
|
5244
|
-
var CreateMaeveLessonInputSchema = external_exports.object({
|
|
5245
|
-
product: external_exports.string().min(1).max(120),
|
|
5246
|
-
statement: external_exports.string().min(1).max(1e3),
|
|
5247
|
-
scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5248
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5249
|
-
evidence: external_exports.array(MaeveLessonEvidenceSchema).default([]),
|
|
5250
|
-
status: MaeveLessonStatusSchema.default("candidate"),
|
|
5251
|
-
lastSeenAt: external_exports.string().datetime().optional()
|
|
5252
|
-
});
|
|
5253
|
-
var PromoteMaeveLessonInputSchema = external_exports.object({
|
|
5254
|
-
id: external_exports.string().uuid(),
|
|
5255
|
-
status: MaeveLessonStatusSchema,
|
|
5256
|
-
appendEvidence: external_exports.array(MaeveLessonEvidenceSchema).optional()
|
|
5257
|
-
});
|
|
5258
|
-
var RecallMaeveLessonsQuerySchema = external_exports.object({
|
|
5259
|
-
product: external_exports.string().min(1).max(120).optional(),
|
|
5260
|
-
taskType: external_exports.string().min(1).max(120).optional(),
|
|
5261
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5262
|
-
limit: external_exports.number().int().positive().max(10).default(5),
|
|
5263
|
-
/**
|
|
5264
|
-
* Free-text query for semantic (pgvector cosine) recall. When set and an
|
|
5265
|
-
* EmbeddingProvider is configured, recallMaeveLessons embeds this text and
|
|
5266
|
-
* retrieves by cosine similarity, with exact-tag matches as a boost.
|
|
5267
|
-
* Falls back to exact-class matching when the provider is NoOp.
|
|
5268
|
-
*/
|
|
5269
|
-
semanticQuery: external_exports.string().min(1).max(500).optional()
|
|
5270
|
-
});
|
|
5271
|
-
var MaeveLessonSeedAnchorSchema = external_exports.object({
|
|
5272
|
-
commit: external_exports.string().regex(/^[0-9a-f]{40}$/i, "commit must be a full 40-character git SHA"),
|
|
5273
|
-
pr: external_exports.number().int().positive().nullable(),
|
|
5274
|
-
summary: external_exports.string().min(1).max(1e3)
|
|
5275
|
-
});
|
|
5276
|
-
var MaeveLessonSeedSchema = external_exports.object({
|
|
5277
|
-
statement: external_exports.string().min(1).max(1e3),
|
|
5278
|
-
scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5279
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5280
|
-
anchors: external_exports.array(MaeveLessonSeedAnchorSchema).min(1),
|
|
5281
|
-
lastSeenAt: external_exports.string().datetime()
|
|
5282
|
-
});
|
|
5283
|
-
var ReviewFindingSeveritySchema = external_exports.enum(["critical", "high", "medium", "low"]);
|
|
5284
|
-
var ReviewFindingLessonInputSchema = external_exports.object({
|
|
5285
|
-
studioId: external_exports.string().min(1),
|
|
5286
|
-
findingStudioId: external_exports.string().min(1),
|
|
5287
|
-
product: external_exports.string().min(1).max(120),
|
|
5288
|
-
repository: external_exports.string().min(1).max(240),
|
|
5289
|
-
pullRequestNumber: external_exports.number().int().positive(),
|
|
5290
|
-
findingText: external_exports.string().min(1).max(4e3),
|
|
5291
|
-
severity: ReviewFindingSeveritySchema,
|
|
5292
|
-
reviewer: external_exports.string().min(1).max(120),
|
|
5293
|
-
remediatingCommitSha: external_exports.string().min(4).max(64),
|
|
5294
|
-
/** The durable, reusable rule distilled from the finding — NOT the finding text verbatim. */
|
|
5295
|
-
lessonStatement: external_exports.string().min(1).max(1e3),
|
|
5296
|
-
scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5297
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5298
|
-
occurredAt: external_exports.string().datetime()
|
|
5299
|
-
});
|
|
5300
|
-
|
|
5301
|
-
// ../shared/src/schemas/operator-trace.ts
|
|
5302
|
-
var TRACE_ACTORS = [
|
|
5303
|
-
"human",
|
|
5304
|
-
"cowork",
|
|
5305
|
-
"claude-code",
|
|
5306
|
-
"codex",
|
|
5307
|
-
"goal-runner",
|
|
5308
|
-
"ci"
|
|
5309
|
-
];
|
|
5310
|
-
var TraceActorSchema = external_exports.enum(TRACE_ACTORS);
|
|
5311
|
-
var TRACE_SOURCES = [
|
|
5312
|
-
"shell",
|
|
5313
|
-
"cowork",
|
|
5314
|
-
"claude-code",
|
|
5315
|
-
"codex",
|
|
5316
|
-
"goal-runner",
|
|
5317
|
-
"github"
|
|
5318
|
-
];
|
|
5319
|
-
var TraceSourceSchema = external_exports.enum(TRACE_SOURCES);
|
|
5320
|
-
var TraceProvenanceSchema = external_exports.object({
|
|
5321
|
-
source: TraceSourceSchema,
|
|
5322
|
-
/** Absolute path of the source file/dir, or the gh query for CI events. */
|
|
5323
|
-
path: external_exports.string().min(1).max(1e3),
|
|
5324
|
-
/** Line number, session id, or PR number locating the row inside the source. */
|
|
5325
|
-
locator: external_exports.string().min(1).max(200).optional()
|
|
5326
|
-
});
|
|
5327
|
-
var TraceRecordSchema = external_exports.object({
|
|
5328
|
-
t: external_exports.string().datetime(),
|
|
5329
|
-
actor: TraceActorSchema,
|
|
5330
|
-
action: external_exports.string().min(1).max(2e3),
|
|
5331
|
-
target: external_exports.string().max(1e3).default(""),
|
|
5332
|
-
outcome: external_exports.string().max(2e3).default(""),
|
|
5333
|
-
product: external_exports.string().min(1).max(120).optional(),
|
|
5334
|
-
provenance: TraceProvenanceSchema
|
|
5335
|
-
});
|
|
5336
|
-
var ShellRedactionSchema = external_exports.enum(["none", "secret", "unclassified"]);
|
|
5337
|
-
var ShellTraceEntrySchema = external_exports.object({
|
|
5338
|
-
ts: external_exports.string().datetime(),
|
|
5339
|
-
cwd: external_exports.string().min(1).max(1e3),
|
|
5340
|
-
command: external_exports.string().min(1).max(4e3),
|
|
5341
|
-
exitCode: external_exports.number().int(),
|
|
5342
|
-
shellSessionId: external_exports.string().min(1).max(200),
|
|
5343
|
-
redaction: ShellRedactionSchema
|
|
5344
|
-
});
|
|
5345
|
-
var TraceSourceReportSchema = external_exports.discriminatedUnion("status", [
|
|
5346
|
-
external_exports.object({
|
|
5347
|
-
status: external_exports.literal("ok"),
|
|
5348
|
-
source: TraceSourceSchema,
|
|
5349
|
-
recordCount: external_exports.number().int().nonnegative(),
|
|
5350
|
-
/** Files/entries present but skipped (unparseable, filtered) — named, not silent. */
|
|
5351
|
-
skipped: external_exports.array(external_exports.string().min(1).max(500)).default([])
|
|
5352
|
-
}),
|
|
5353
|
-
external_exports.object({
|
|
5354
|
-
status: external_exports.literal("dark"),
|
|
5355
|
-
source: TraceSourceSchema,
|
|
5356
|
-
reason: external_exports.string().min(1).max(500)
|
|
5357
|
-
})
|
|
5358
|
-
]);
|
|
5359
|
-
var OperatorTimelineSchema = external_exports.object({
|
|
5360
|
-
records: external_exports.array(TraceRecordSchema),
|
|
5361
|
-
sources: external_exports.array(TraceSourceReportSchema)
|
|
5362
|
-
});
|
|
5363
|
-
|
|
5364
|
-
// ../shared/src/schemas/witan.ts
|
|
4073
|
+
// src/witan/schemas.ts
|
|
5365
4074
|
var WITAN_RUBRIC_VERSION_V1 = "witan-rubric-v1-2026-06-24";
|
|
5366
4075
|
var WITAN_RUBRIC_VERSION_V2 = "witan-rubric-v2-2026-07-12";
|
|
5367
4076
|
var WITAN_RUBRIC_VERSION_V3 = "witan-rubric-v3-2026-07-13";
|
|
@@ -5391,11 +4100,9 @@ var WITAN_TRADING_RUBRIC_V0_CRITERION_IDS = [
|
|
|
5391
4100
|
"audit-completeness",
|
|
5392
4101
|
"claim-reality"
|
|
5393
4102
|
];
|
|
5394
|
-
var WITAN_QUANT_INTEGRITY_RUBRIC_V0_CRITERION_IDS = ["quant-integrity"];
|
|
5395
4103
|
var WitanCriterionIdSchema = external_exports.enum([
|
|
5396
4104
|
...WITAN_CRITERION_IDS,
|
|
5397
|
-
...WITAN_TRADING_RUBRIC_V0_CRITERION_IDS
|
|
5398
|
-
...WITAN_QUANT_INTEGRITY_RUBRIC_V0_CRITERION_IDS
|
|
4105
|
+
...WITAN_TRADING_RUBRIC_V0_CRITERION_IDS
|
|
5399
4106
|
]);
|
|
5400
4107
|
var WitanTradingCriterionIdSchema = external_exports.enum(WITAN_TRADING_RUBRIC_V0_CRITERION_IDS);
|
|
5401
4108
|
var WitanCriterionCategorySchema = external_exports.enum([
|
|
@@ -5423,8 +4130,6 @@ var WitanEvidenceKindSchema = external_exports.enum([
|
|
|
5423
4130
|
"commit",
|
|
5424
4131
|
"coverage",
|
|
5425
4132
|
"dependency_report",
|
|
5426
|
-
"dispatch_log",
|
|
5427
|
-
"maeve_trace",
|
|
5428
4133
|
"prod_check",
|
|
5429
4134
|
"pull_request",
|
|
5430
4135
|
"repository",
|
|
@@ -5537,1005 +4242,640 @@ var WitanConsumedSignalSummarySchema = external_exports.object({
|
|
|
5537
4242
|
// this field always carries every finding.
|
|
5538
4243
|
findings: external_exports.array(WitanInputSignalFindingSchema).default([])
|
|
5539
4244
|
}).strict();
|
|
5540
|
-
var
|
|
4245
|
+
var WitanScoredVerdictSchema = external_exports.enum([
|
|
4246
|
+
"verified",
|
|
4247
|
+
"conditional",
|
|
4248
|
+
"at_risk",
|
|
4249
|
+
"unverified"
|
|
4250
|
+
]);
|
|
4251
|
+
var WitanReportVerdictSchema = external_exports.union([
|
|
4252
|
+
WitanScoredVerdictSchema,
|
|
4253
|
+
external_exports.literal("insufficient_source")
|
|
4254
|
+
]);
|
|
4255
|
+
function witanVerdictForScore(score) {
|
|
4256
|
+
if (score >= 3.5) return "verified";
|
|
4257
|
+
if (score >= 2.5) return "conditional";
|
|
4258
|
+
if (score >= 1.5) return "at_risk";
|
|
4259
|
+
return "unverified";
|
|
4260
|
+
}
|
|
4261
|
+
var WitanReportCommonSchema = external_exports.object({
|
|
5541
4262
|
productSlug: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/),
|
|
5542
4263
|
productDisplayName: external_exports.string().min(1).max(120),
|
|
5543
4264
|
repo: WitanRepoRefSchema,
|
|
5544
4265
|
generatedAt: external_exports.string().datetime({ offset: true }),
|
|
5545
4266
|
rubricVersion: external_exports.string().min(1).max(120),
|
|
5546
|
-
codeTrustScore: external_exports.number().min(0).max(4),
|
|
5547
|
-
processTrustScore: external_exports.number().min(0).max(4),
|
|
5548
|
-
overallScore: external_exports.number().min(0).max(4),
|
|
5549
4267
|
// Rubric-driven: length matches whatever rubric produced this report, not a fixed enum.
|
|
5550
4268
|
criteria: external_exports.array(WitanCriterionScoreSchema).min(1),
|
|
5551
4269
|
consumedSignals: external_exports.array(WitanConsumedSignalSummarySchema).optional(),
|
|
4270
|
+
archetype: WitanRepoArchetypeSchema.optional()
|
|
4271
|
+
});
|
|
4272
|
+
var WitanScoredReportSchema = WitanReportCommonSchema.extend({
|
|
4273
|
+
verdict: WitanScoredVerdictSchema,
|
|
4274
|
+
codeTrustScore: external_exports.number().min(0).max(4),
|
|
4275
|
+
processTrustScore: external_exports.number().min(0).max(4),
|
|
4276
|
+
overallScore: external_exports.number().min(0).max(4),
|
|
5552
4277
|
// Present only when the rubric has more than two criterion categories — the legacy
|
|
5553
4278
|
// codeTrustScore/processTrustScore pair can't losslessly represent 3+ category buckets.
|
|
5554
4279
|
categoryScores: external_exports.record(external_exports.string(), external_exports.number().min(0).max(4)).optional(),
|
|
5555
|
-
|
|
5556
|
-
// callers that don't classify an archetype (e.g. the trading rubric). insufficientSourceReason
|
|
5557
|
-
// is present only for the non-source archetypes ('docs_only' | 'binary_only' |
|
|
5558
|
-
// 'unrecognised_ecosystem' | 'empty') — its presence is what presentation layers
|
|
5559
|
-
// (badge/terminal/verdict) key off to show an explicit insufficient-source verdict instead of
|
|
5560
|
-
// a confident numeric score.
|
|
5561
|
-
archetype: WitanRepoArchetypeSchema.optional(),
|
|
5562
|
-
insufficientSourceReason: external_exports.string().min(1).max(2e3).optional()
|
|
5563
|
-
}).strict();
|
|
5564
|
-
|
|
5565
|
-
// ../shared/src/schemas/work-item.ts
|
|
5566
|
-
var WorkItemTypeSchema = external_exports.enum(["feature", "bug"]);
|
|
5567
|
-
var WorkItemPrioritySchema = external_exports.enum(["low", "normal", "high", "urgent"]);
|
|
5568
|
-
var WorkItemStatusSchema = external_exports.enum([
|
|
5569
|
-
"submitted",
|
|
5570
|
-
"scoped",
|
|
5571
|
-
"dispatched",
|
|
5572
|
-
"pr_open",
|
|
5573
|
-
"done",
|
|
5574
|
-
"declined"
|
|
5575
|
-
]);
|
|
5576
|
-
var CreateWorkItemInputSchema = external_exports.object({
|
|
5577
|
-
productId: external_exports.string().uuid(),
|
|
5578
|
-
type: WorkItemTypeSchema,
|
|
5579
|
-
title: external_exports.string().min(3).max(180),
|
|
5580
|
-
description: external_exports.string().min(8).max(2e4),
|
|
5581
|
-
acceptanceCriteria: external_exports.string().max(2e4).optional(),
|
|
5582
|
-
priority: WorkItemPrioritySchema.default("normal")
|
|
5583
|
-
}).strict();
|
|
5584
|
-
var ScopeWorkItemInputSchema = external_exports.object({
|
|
5585
|
-
scopedTask: external_exports.string().min(8).max(2e4).optional()
|
|
5586
|
-
}).strict();
|
|
5587
|
-
var ListWorkItemsQuerySchema = external_exports.object({
|
|
5588
|
-
productId: external_exports.string().uuid().optional(),
|
|
5589
|
-
status: WorkItemStatusSchema.optional()
|
|
5590
|
-
}).strict();
|
|
5591
|
-
var DispatchWorkItemInputSchema = external_exports.object({
|
|
5592
|
-
executor: external_exports.enum(["claude-code", "codex"]).default("codex"),
|
|
5593
|
-
mode: external_exports.enum(["dry-run", "execute"]).default("dry-run")
|
|
5594
|
-
}).strict();
|
|
5595
|
-
|
|
5596
|
-
// ../shared/src/schemas/goal-frontmatter.ts
|
|
5597
|
-
var GoalStreamKindSchema = external_exports.enum(["code", "process"]);
|
|
5598
|
-
var GoalPrioritySchema = external_exports.enum(["p0", "p1", "p2"]);
|
|
5599
|
-
var GoalFrontmatterExtrasSchema = external_exports.object({
|
|
5600
|
-
stream: external_exports.string().min(1).nullable().default(null),
|
|
5601
|
-
order: external_exports.number().int().nullable().default(null),
|
|
5602
|
-
dependsOn: external_exports.array(external_exports.string().min(1)).default([]),
|
|
5603
|
-
priority: GoalPrioritySchema.nullable().default(null),
|
|
5604
|
-
kind: GoalStreamKindSchema.default("code")
|
|
5605
|
-
});
|
|
5606
|
-
|
|
5607
|
-
// ../shared/src/schemas/stream.ts
|
|
5608
|
-
var StreamSchema = external_exports.object({
|
|
5609
|
-
id: external_exports.string().uuid(),
|
|
5610
|
-
studioId: external_exports.string().uuid(),
|
|
5611
|
-
name: external_exports.string().min(1).max(120),
|
|
5612
|
-
tag: external_exports.string().max(60).nullable(),
|
|
5613
|
-
kind: GoalStreamKindSchema,
|
|
5614
|
-
orderIndex: external_exports.number().int(),
|
|
5615
|
-
createdAt: external_exports.coerce.date(),
|
|
5616
|
-
updatedAt: external_exports.coerce.date()
|
|
5617
|
-
});
|
|
5618
|
-
var StreamItemSchema = external_exports.object({
|
|
5619
|
-
id: external_exports.string().uuid(),
|
|
5620
|
-
studioId: external_exports.string().uuid(),
|
|
5621
|
-
streamId: external_exports.string().uuid(),
|
|
5622
|
-
orderIndex: external_exports.number().int(),
|
|
5623
|
-
title: external_exports.string().min(1).max(200),
|
|
5624
|
-
/** docs/orchestration/goal_*.md filename (no extension) for code items; null for process items. */
|
|
5625
|
-
goalName: external_exports.string().min(1).nullable(),
|
|
5626
|
-
refLabel: external_exports.string().max(60).nullable(),
|
|
5627
|
-
/** Free-form governed-run prompt text (mirrors the prototype's per-item `run` string). Null = no run control shown. */
|
|
5628
|
-
runPrompt: external_exports.string().min(1).nullable(),
|
|
5629
|
-
createdAt: external_exports.coerce.date(),
|
|
5630
|
-
updatedAt: external_exports.coerce.date()
|
|
5631
|
-
});
|
|
5632
|
-
var StreamItemDisplayStatusSchema = external_exports.enum([
|
|
5633
|
-
"done",
|
|
5634
|
-
"in-review",
|
|
5635
|
-
"running",
|
|
5636
|
-
"queued",
|
|
5637
|
-
"blocked",
|
|
5638
|
-
"local-unknown"
|
|
5639
|
-
]);
|
|
5640
|
-
|
|
5641
|
-
// ../shared/src/schemas/runner-dispatch.ts
|
|
5642
|
-
var RUNNER_DISPATCH_MODES = ["dry-run", "execute"];
|
|
5643
|
-
var RunnerDispatchModeSchema = external_exports.enum(RUNNER_DISPATCH_MODES);
|
|
5644
|
-
var RUNNER_DISPATCH_STATUSES = ["queued", "claimed", "running", "done", "failed"];
|
|
5645
|
-
var RunnerDispatchStatusSchema = external_exports.enum(RUNNER_DISPATCH_STATUSES);
|
|
5646
|
-
var GOAL_CARD_PATTERN = /^docs\/orchestration\/[A-Za-z0-9_./-]+\.md$/;
|
|
5647
|
-
function isAllowedGoalCardPath(goalCard) {
|
|
5648
|
-
if (!GOAL_CARD_PATTERN.test(goalCard)) return false;
|
|
5649
|
-
return goalCard.split("/").every((segment) => segment !== "." && segment !== "..");
|
|
5650
|
-
}
|
|
5651
|
-
var GoalCardPathSchema = external_exports.string().min(1).max(300).refine(isAllowedGoalCardPath, { message: "goal_card_invalid" });
|
|
5652
|
-
var RunnerDispatchRequestSchema = external_exports.object({
|
|
5653
|
-
goalCard: GoalCardPathSchema,
|
|
5654
|
-
stream: external_exports.string().min(1).max(120).optional(),
|
|
5655
|
-
mode: RunnerDispatchModeSchema
|
|
5656
|
-
});
|
|
5657
|
-
|
|
5658
|
-
// ../shared/src/schemas/witan-metrics-manifest.ts
|
|
5659
|
-
var WITAN_METRICS_MANIFEST_SCHEMA_VERSION = "witan-metrics-manifest-v0";
|
|
5660
|
-
var WitanMetricsManifestReturnsFrequencySchema = external_exports.enum([
|
|
5661
|
-
"daily",
|
|
5662
|
-
"weekly",
|
|
5663
|
-
"monthly",
|
|
5664
|
-
"annual"
|
|
5665
|
-
]);
|
|
5666
|
-
var WitanMetricsManifestFoldSchema = external_exports.object({
|
|
5667
|
-
foldId: external_exports.string().min(1).max(80),
|
|
5668
|
-
inSampleSharpe: external_exports.number().optional(),
|
|
5669
|
-
outOfSampleSharpe: external_exports.number().optional()
|
|
5670
|
-
}).strict();
|
|
5671
|
-
var WitanMetricsManifestCscvTrialSchema = external_exports.object({
|
|
5672
|
-
trialId: external_exports.string().min(1).max(80),
|
|
5673
|
-
blockReturns: external_exports.array(external_exports.number()).min(2)
|
|
5674
|
-
}).strict();
|
|
5675
|
-
var WitanMetricsManifestCscvSchema = external_exports.object({
|
|
5676
|
-
// Must be even (split into IS/OOS halves) — enforced by the grader, not the schema.
|
|
5677
|
-
blocks: external_exports.number().int().min(4).max(16),
|
|
5678
|
-
trials: external_exports.array(WitanMetricsManifestCscvTrialSchema).min(2).max(200)
|
|
5679
|
-
}).strict();
|
|
5680
|
-
var WitanMetricsManifestCostModelSchema = external_exports.object({
|
|
5681
|
-
feeBps: external_exports.number().min(0).optional(),
|
|
5682
|
-
slippageBps: external_exports.number().min(0).optional(),
|
|
5683
|
-
borrowBps: external_exports.number().min(0).optional(),
|
|
5684
|
-
notes: external_exports.string().min(1).max(300).optional()
|
|
5685
|
-
}).strict();
|
|
5686
|
-
var WitanMetricsManifestParameterPointSchema = external_exports.object({
|
|
5687
|
-
// Human-readable label for this point (e.g. "72" or "72 bars") — evidence/display only.
|
|
5688
|
-
paramLabel: external_exports.string().min(1).max(80),
|
|
5689
|
-
// The point's position on its swept axis, used to find its nearest neighbors by distance.
|
|
5690
|
-
paramValue: external_exports.number(),
|
|
5691
|
-
outOfSampleSharpe: external_exports.number()
|
|
5692
|
-
}).strict();
|
|
5693
|
-
var WitanMetricsManifestParameterSweepSchema = external_exports.object({
|
|
5694
|
-
// Name of the swept parameter (e.g. "lookback_bars") — evidence/display only.
|
|
5695
|
-
paramName: external_exports.string().min(1).max(80),
|
|
5696
|
-
points: external_exports.array(WitanMetricsManifestParameterPointSchema).min(3).max(500)
|
|
5697
|
-
}).strict();
|
|
5698
|
-
var WitanMetricsManifestLabelSourceSchema = external_exports.enum([
|
|
5699
|
-
"real_forward_returns",
|
|
5700
|
-
"synthetic",
|
|
5701
|
-
"unknown"
|
|
5702
|
-
]);
|
|
5703
|
-
var WitanMetricsManifestSchema = external_exports.object({
|
|
5704
|
-
schemaVersion: external_exports.literal(WITAN_METRICS_MANIFEST_SCHEMA_VERSION),
|
|
5705
|
-
strategyName: external_exports.string().min(1).max(200).optional(),
|
|
5706
|
-
// The headline reported Sharpe ratio the target repo is claiming.
|
|
5707
|
-
reportedSharpe: external_exports.number(),
|
|
5708
|
-
// How many trials/backtests were run in the search that produced reportedSharpe (the
|
|
5709
|
-
// "1-of-42" count) — required so the grader can correct for selection bias.
|
|
5710
|
-
trialCount: external_exports.number().int().positive(),
|
|
5711
|
-
// Track-record length in return observations (e.g. 252 for a year of daily returns) —
|
|
5712
|
-
// the `n` in the Probabilistic/Deflated Sharpe Ratio formula.
|
|
5713
|
-
trackRecordObservations: external_exports.number().int().positive(),
|
|
5714
|
-
returnsFrequency: WitanMetricsManifestReturnsFrequencySchema.default("daily"),
|
|
5715
|
-
// Skew/kurtosis of the returns distribution; default to the normal-distribution values
|
|
5716
|
-
// (0 skew, kurtosis 3) when the repo does not report them.
|
|
5717
|
-
skewness: external_exports.number().default(0),
|
|
5718
|
-
kurtosis: external_exports.number().min(0).default(3),
|
|
5719
|
-
// Whether reportedSharpe is net of trading costs (fees/slippage/borrow/roll).
|
|
5720
|
-
netOfCosts: external_exports.boolean(),
|
|
5721
|
-
costModel: WitanMetricsManifestCostModelSchema.optional(),
|
|
5722
|
-
// Per-fold in-sample vs out-of-sample breakdown, when the repo reports one.
|
|
5723
|
-
folds: external_exports.array(WitanMetricsManifestFoldSchema).default([]),
|
|
5724
|
-
// Per-trial, per-block performance matrix for the CSCV/PBO computation, when available.
|
|
5725
|
-
cscv: WitanMetricsManifestCscvSchema.optional(),
|
|
5726
|
-
// Parameter-sweep breakdown for the run-tier (L3b) parameter-neighborhood robustness
|
|
5727
|
-
// grader, when the run swept a parameter (e.g. a lookback window) and recorded OOS
|
|
5728
|
-
// performance at each swept value.
|
|
5729
|
-
parameterSweep: WitanMetricsManifestParameterSweepSchema.optional(),
|
|
5730
|
-
// Provenance of the labels behind reportedSharpe (labelling-integrity, L1+artifact tier).
|
|
5731
|
-
labelSource: WitanMetricsManifestLabelSourceSchema.optional()
|
|
4280
|
+
insufficientSourceReason: external_exports.never().optional()
|
|
5732
4281
|
}).strict();
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
command: external_exports.array(external_exports.string().min(1).max(300)).min(1).max(20),
|
|
5742
|
-
// Relative path (within the target repo) to the data the strategy should backtest against.
|
|
5743
|
-
dataPath: external_exports.string().min(1).max(500).optional(),
|
|
5744
|
-
// Backtest window, as the target repo defines its own date strings (ISO-8601 recommended).
|
|
5745
|
-
// Optional — a strategy may declare its own default window instead.
|
|
5746
|
-
windowStart: external_exports.string().min(1).max(40).optional(),
|
|
5747
|
-
windowEnd: external_exports.string().min(1).max(40).optional(),
|
|
5748
|
-
// Relative path (within the sandboxed workspace) the entrypoint must write its raw result
|
|
5749
|
-
// to — see WitanStrategyRunResultSchema below.
|
|
5750
|
-
outputPath: external_exports.string().min(1).max(300).default("witan-run-result.json"),
|
|
5751
|
-
timeoutMs: external_exports.number().int().positive().max(30 * 60 * 1e3).default(2 * 60 * 1e3),
|
|
5752
|
-
// Explicit opt-in egress allowlist. Empty by default — no network from the sandboxed run
|
|
5753
|
-
// unless the target repo explicitly whitelists hosts here.
|
|
5754
|
-
allowedHosts: external_exports.array(external_exports.string().min(1).max(255)).max(20).default([])
|
|
4282
|
+
var WitanAbstainedReportSchema = WitanReportCommonSchema.extend({
|
|
4283
|
+
verdict: external_exports.literal("insufficient_source"),
|
|
4284
|
+
// Null is deliberate and explicit: omission is ambiguous, while zero is a real score.
|
|
4285
|
+
codeTrustScore: external_exports.null(),
|
|
4286
|
+
processTrustScore: external_exports.null(),
|
|
4287
|
+
overallScore: external_exports.null(),
|
|
4288
|
+
categoryScores: external_exports.never().optional(),
|
|
4289
|
+
insufficientSourceReason: external_exports.string().min(1).max(2e3)
|
|
5755
4290
|
}).strict();
|
|
5756
|
-
var
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
"acknowledge_canary_alert",
|
|
5765
|
-
"update_status_md",
|
|
5766
|
-
"provision_product",
|
|
5767
|
-
"dispatch_dev_task"
|
|
5768
|
-
]);
|
|
5769
|
-
var TacticalActionStatusSchema = external_exports.enum(["executed", "blocked", "dry_run"]);
|
|
5770
|
-
var TacticalActionPolicySchema = external_exports.object({
|
|
5771
|
-
studioId: external_exports.string().uuid(),
|
|
5772
|
-
productId: external_exports.string().uuid(),
|
|
5773
|
-
actionType: TacticalActionTypeSchema,
|
|
5774
|
-
allowed: external_exports.boolean(),
|
|
5775
|
-
dryRun: external_exports.boolean(),
|
|
5776
|
-
promotedAt: external_exports.coerce.date().nullable(),
|
|
5777
|
-
forceEnableReason: external_exports.string().nullable()
|
|
5778
|
-
});
|
|
5779
|
-
var BaseActionSchema = external_exports.object({
|
|
5780
|
-
actionType: TacticalActionTypeSchema,
|
|
5781
|
-
productId: external_exports.string().uuid(),
|
|
5782
|
-
coordinatorSessionId: external_exports.string().uuid().nullable().optional(),
|
|
5783
|
-
customerFacingProduction: external_exports.boolean().default(false)
|
|
5784
|
-
});
|
|
5785
|
-
var MergePrTacticalActionSchema = BaseActionSchema.extend({
|
|
5786
|
-
actionType: external_exports.literal("merge_pr_auto_merge_safe"),
|
|
5787
|
-
repository: external_exports.string().min(1),
|
|
5788
|
-
pullRequestNumber: external_exports.number().int().positive(),
|
|
5789
|
-
labels: external_exports.array(external_exports.string()),
|
|
5790
|
-
ciStatus: external_exports.enum(["green", "red", "unknown"]),
|
|
5791
|
-
humanApprovals: external_exports.number().int().nonnegative(),
|
|
5792
|
-
coworkClaudeApprovedStatus: external_exports.enum(["green", "red", "unknown"]),
|
|
5793
|
-
// The PR head SHA captured at the SAME live precondition snapshot that
|
|
5794
|
-
// verified the label/CI/approvals/cowork-claude-approved gates. Threaded
|
|
5795
|
-
// through to the GitHub merge call as the conditional `sha` parameter so a
|
|
5796
|
-
// commit that lands between the snapshot and the merge (a fast follow-up
|
|
5797
|
-
// push, or a re-triggered CI run resetting status) can never be
|
|
5798
|
-
// squash-merged unverified — GitHub rejects the merge with 409 instead.
|
|
5799
|
-
headSha: external_exports.string().min(1)
|
|
5800
|
-
});
|
|
5801
|
-
var DeployStagingTacticalActionSchema = BaseActionSchema.extend({
|
|
5802
|
-
actionType: external_exports.literal("deploy_staging"),
|
|
5803
|
-
environment: external_exports.literal("staging"),
|
|
5804
|
-
mainStatus: external_exports.enum(["green", "red", "unknown"]),
|
|
5805
|
-
stagingStatus: external_exports.enum(["green", "red", "unknown"])
|
|
5806
|
-
});
|
|
5807
|
-
var AcknowledgeCanaryAlertTacticalActionSchema = BaseActionSchema.extend({
|
|
5808
|
-
actionType: external_exports.literal("acknowledge_canary_alert"),
|
|
5809
|
-
alertId: external_exports.string().min(1),
|
|
5810
|
-
fingerprint: external_exports.string().min(1),
|
|
5811
|
-
knownFalsePositiveFingerprints: external_exports.array(external_exports.string()).default([])
|
|
5812
|
-
});
|
|
5813
|
-
var UpdateStatusMdTacticalActionSchema = BaseActionSchema.extend({
|
|
5814
|
-
actionType: external_exports.literal("update_status_md"),
|
|
5815
|
-
source: external_exports.literal("daily_brief_synthesis"),
|
|
5816
|
-
statusMarkdown: external_exports.string().min(1).max(2e4)
|
|
5817
|
-
});
|
|
5818
|
-
var ProvisionProductTacticalActionSchema = BaseActionSchema.extend({
|
|
5819
|
-
actionType: external_exports.literal("provision_product"),
|
|
5820
|
-
productName: external_exports.string().min(1).max(80),
|
|
5821
|
-
vertical: external_exports.string().min(1).max(80),
|
|
5822
|
-
repoTarget: external_exports.string().min(1),
|
|
5823
|
-
templateRef: external_exports.string().min(1),
|
|
5824
|
-
scopeNotes: external_exports.string().max(2e3).optional()
|
|
5825
|
-
});
|
|
5826
|
-
var DispatchDevTaskTacticalActionSchema = BaseActionSchema.extend({
|
|
5827
|
-
actionType: external_exports.literal("dispatch_dev_task"),
|
|
5828
|
-
repo: RepoRefSchema,
|
|
5829
|
-
task: external_exports.string().min(1).max(2e4),
|
|
5830
|
-
executor: CodingAgentExecutorSchema
|
|
5831
|
-
});
|
|
5832
|
-
var TacticalActionSchema = external_exports.discriminatedUnion("actionType", [
|
|
5833
|
-
MergePrTacticalActionSchema,
|
|
5834
|
-
DeployStagingTacticalActionSchema,
|
|
5835
|
-
AcknowledgeCanaryAlertTacticalActionSchema,
|
|
5836
|
-
UpdateStatusMdTacticalActionSchema,
|
|
5837
|
-
ProvisionProductTacticalActionSchema,
|
|
5838
|
-
DispatchDevTaskTacticalActionSchema
|
|
5839
|
-
]);
|
|
5840
|
-
var TacticalActionContextSchema = external_exports.object({
|
|
5841
|
-
studioId: external_exports.string().uuid(),
|
|
5842
|
-
actorUserId: external_exports.string().uuid().nullable().optional(),
|
|
5843
|
-
requestedAt: external_exports.coerce.date().optional()
|
|
4291
|
+
var StrictWitanReportSchema = external_exports.union([WitanScoredReportSchema, WitanAbstainedReportSchema]).superRefine((report, context) => {
|
|
4292
|
+
if (report.verdict !== "insufficient_source" && report.verdict !== witanVerdictForScore(report.overallScore)) {
|
|
4293
|
+
context.addIssue({
|
|
4294
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4295
|
+
path: ["verdict"],
|
|
4296
|
+
message: `verdict does not match overallScore ${report.overallScore}`
|
|
4297
|
+
});
|
|
4298
|
+
}
|
|
5844
4299
|
});
|
|
5845
|
-
var
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
4300
|
+
var WitanReportSchema = external_exports.preprocess((value) => {
|
|
4301
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && !("verdict" in value) && !("insufficientSourceReason" in value) && typeof value.overallScore === "number") {
|
|
4302
|
+
return {
|
|
4303
|
+
...value,
|
|
4304
|
+
verdict: witanVerdictForScore(value.overallScore)
|
|
4305
|
+
};
|
|
4306
|
+
}
|
|
4307
|
+
return value;
|
|
4308
|
+
}, StrictWitanReportSchema);
|
|
4309
|
+
var WITAN_ATTESTATION_STATEMENT_TYPE = "https://in-toto.io/Statement/v1";
|
|
4310
|
+
var WITAN_ATTESTATION_PREDICATE_TYPE = "https://cejel.dev/attestations/scan/v1";
|
|
4311
|
+
var WitanAttestationOutcomeSchema = external_exports.discriminatedUnion("status", [
|
|
5851
4312
|
external_exports.object({
|
|
5852
|
-
status: external_exports.literal("
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
4313
|
+
status: external_exports.literal("scored"),
|
|
4314
|
+
overallScore: external_exports.number().min(0).max(4),
|
|
4315
|
+
codeTrustScore: external_exports.number().min(0).max(4),
|
|
4316
|
+
processTrustScore: external_exports.number().min(0).max(4)
|
|
4317
|
+
}).strict(),
|
|
5856
4318
|
external_exports.object({
|
|
5857
|
-
status: external_exports.literal("
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
wouldHaveDone: external_exports.record(external_exports.unknown())
|
|
5861
|
-
})
|
|
5862
|
-
]);
|
|
5863
|
-
var TacticalActionLogEntrySchema = external_exports.object({
|
|
5864
|
-
id: external_exports.string().uuid(),
|
|
5865
|
-
studioId: external_exports.string().uuid(),
|
|
5866
|
-
productId: external_exports.string().uuid(),
|
|
5867
|
-
product: external_exports.string().nullable().optional(),
|
|
5868
|
-
coordinatorSessionId: external_exports.string().uuid().nullable(),
|
|
5869
|
-
actionType: TacticalActionTypeSchema.or(external_exports.string()),
|
|
5870
|
-
context: external_exports.record(external_exports.unknown()),
|
|
5871
|
-
permitResult: external_exports.record(external_exports.unknown()),
|
|
5872
|
-
status: TacticalActionStatusSchema,
|
|
5873
|
-
outcome: external_exports.string().nullable(),
|
|
5874
|
-
wouldHaveDone: external_exports.record(external_exports.unknown()).nullable(),
|
|
5875
|
-
attemptedAt: external_exports.string(),
|
|
5876
|
-
executedAt: external_exports.string().nullable()
|
|
5877
|
-
});
|
|
5878
|
-
|
|
5879
|
-
// ../shared/src/schemas/index.ts
|
|
5880
|
-
var StudioSchema = external_exports.object({
|
|
5881
|
-
id: external_exports.string().uuid(),
|
|
5882
|
-
name: external_exports.string().min(1).max(100),
|
|
5883
|
-
billingStatus: external_exports.enum(["trial", "active", "past_due", "cancelled"]),
|
|
5884
|
-
planTier: external_exports.enum(["trial", "solo", "studio", "studio_plus", "self_hosted", "enterprise"]),
|
|
5885
|
-
onPrem: external_exports.boolean().default(false),
|
|
5886
|
-
createdAt: external_exports.coerce.date()
|
|
5887
|
-
});
|
|
5888
|
-
var HumanSchema = external_exports.object({
|
|
5889
|
-
id: external_exports.string().uuid(),
|
|
5890
|
-
studioId: external_exports.string().uuid(),
|
|
5891
|
-
email: external_exports.string().email(),
|
|
5892
|
-
name: external_exports.string().min(1).max(120),
|
|
5893
|
-
oauthProviders: external_exports.array(external_exports.enum(["google", "microsoft", "apple"])).default([]),
|
|
5894
|
-
role: external_exports.enum(["owner", "member", "advisor", "per_product"]),
|
|
5895
|
-
timezone: external_exports.string(),
|
|
5896
|
-
briefTime: external_exports.string().regex(/^\d{2}:\d{2}$/),
|
|
5897
|
-
createdAt: external_exports.coerce.date()
|
|
5898
|
-
});
|
|
5899
|
-
var ProductSchema = external_exports.object({
|
|
5900
|
-
id: external_exports.string().uuid(),
|
|
5901
|
-
studioId: external_exports.string().uuid(),
|
|
5902
|
-
name: external_exports.string().min(1).max(80),
|
|
5903
|
-
slug: external_exports.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/),
|
|
5904
|
-
status: external_exports.enum(["active", "snoozed", "wound_down", "deleted"]),
|
|
5905
|
-
description: external_exports.string().max(280).optional(),
|
|
5906
|
-
repoUrl: external_exports.string().url().optional(),
|
|
5907
|
-
calendarTag: external_exports.string().optional(),
|
|
5908
|
-
emailLabelPrefix: external_exports.string().optional(),
|
|
5909
|
-
colorHex: external_exports.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
|
|
5910
|
-
scheduleBriefTime: external_exports.string().regex(/^\d{2}:\d{2}$/).optional(),
|
|
5911
|
-
briefTemplateId: external_exports.string().uuid().optional(),
|
|
5912
|
-
regulated: external_exports.boolean().default(false),
|
|
5913
|
-
createdAt: external_exports.coerce.date(),
|
|
5914
|
-
lastTouchedAt: external_exports.coerce.date()
|
|
5915
|
-
});
|
|
5916
|
-
var AgentSchema = external_exports.object({
|
|
5917
|
-
id: external_exports.string().uuid(),
|
|
5918
|
-
studioId: external_exports.string().uuid(),
|
|
5919
|
-
productId: external_exports.string().uuid(),
|
|
5920
|
-
agentType: external_exports.enum(["codex", "claude-code", "cowork", "cursor", "cline", "aider", "other"]),
|
|
5921
|
-
sessionId: external_exports.string().optional(),
|
|
5922
|
-
status: external_exports.enum(["active", "idle", "registered", "archived"]),
|
|
5923
|
-
registeredAt: external_exports.coerce.date(),
|
|
5924
|
-
lastActiveAt: external_exports.coerce.date().optional(),
|
|
5925
|
-
totalCostCentsLifetime: external_exports.number().int().nonnegative().default(0)
|
|
5926
|
-
});
|
|
5927
|
-
var AgentRunSchema = external_exports.object({
|
|
5928
|
-
id: external_exports.string().uuid(),
|
|
5929
|
-
agentId: external_exports.string().uuid(),
|
|
5930
|
-
coordinatorSessionId: external_exports.string().uuid().nullable().optional(),
|
|
5931
|
-
startedAt: external_exports.coerce.date(),
|
|
5932
|
-
completedAt: external_exports.coerce.date().optional(),
|
|
5933
|
-
actionType: external_exports.string(),
|
|
5934
|
-
toolName: external_exports.string().optional(),
|
|
5935
|
-
toolInputSummary: external_exports.string().optional(),
|
|
5936
|
-
toolOutputSummary: external_exports.string().optional(),
|
|
5937
|
-
tokensUsedInput: external_exports.number().int().nonnegative().default(0),
|
|
5938
|
-
tokensUsedOutput: external_exports.number().int().nonnegative().default(0),
|
|
5939
|
-
costCents: external_exports.number().int().nonnegative().default(0),
|
|
5940
|
-
durationMs: external_exports.number().int().nonnegative().default(0),
|
|
5941
|
-
resultStatus: external_exports.enum(["success", "failure", "partial", "timeout"]).optional(),
|
|
5942
|
-
resultSummary: external_exports.string().optional(),
|
|
5943
|
-
filesTouched: external_exports.array(external_exports.string()).default([])
|
|
5944
|
-
});
|
|
5945
|
-
var CoordinatorStatusSchema = external_exports.enum([
|
|
5946
|
-
"draft",
|
|
5947
|
-
"spawned",
|
|
5948
|
-
"in_progress",
|
|
5949
|
-
"reporting",
|
|
5950
|
-
"closed"
|
|
4319
|
+
status: external_exports.literal("abstained"),
|
|
4320
|
+
reason: external_exports.string().min(1).max(2e3)
|
|
4321
|
+
}).strict()
|
|
5951
4322
|
]);
|
|
5952
|
-
var
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
urgency: external_exports.enum(["low", "medium", "high", "critical"]).optional()
|
|
5956
|
-
});
|
|
5957
|
-
var CoordinatorSessionSchema = external_exports.object({
|
|
5958
|
-
id: external_exports.string().uuid(),
|
|
5959
|
-
studioId: external_exports.string().uuid(),
|
|
5960
|
-
productId: external_exports.string().uuid(),
|
|
5961
|
-
promptId: external_exports.string().uuid().nullable(),
|
|
5962
|
-
objective: external_exports.string(),
|
|
5963
|
-
status: CoordinatorStatusSchema,
|
|
5964
|
-
spawnedAt: external_exports.coerce.date().nullable(),
|
|
5965
|
-
closedAt: external_exports.coerce.date().nullable(),
|
|
5966
|
-
escalationPolicy: CoordinatorEscalationPolicySchema.nullable(),
|
|
5967
|
-
outcomeSummary: external_exports.string().nullable(),
|
|
5968
|
-
createdAt: external_exports.coerce.date()
|
|
5969
|
-
});
|
|
5970
|
-
var AgentActivityWindowSchema = external_exports.enum(["24h", "7d", "30d"]);
|
|
5971
|
-
var AgentCostBucketSchema = external_exports.object({
|
|
5972
|
-
key: external_exports.string(),
|
|
5973
|
-
name: external_exports.string(),
|
|
5974
|
-
runCount: external_exports.number().int().nonnegative(),
|
|
5975
|
-
costUsd: external_exports.number().nonnegative()
|
|
5976
|
-
});
|
|
5977
|
-
var AgentCostRollupSchema = external_exports.object({
|
|
5978
|
-
window: AgentActivityWindowSchema,
|
|
5979
|
-
studioTotalUsd: external_exports.number().nonnegative(),
|
|
5980
|
-
runCount: external_exports.number().int().nonnegative(),
|
|
5981
|
-
byAgent: external_exports.array(AgentCostBucketSchema),
|
|
5982
|
-
byProduct: external_exports.array(AgentCostBucketSchema)
|
|
5983
|
-
});
|
|
5984
|
-
var AgentConflictRecordSchema = external_exports.object({
|
|
5985
|
-
file: external_exports.string(),
|
|
5986
|
-
agents: external_exports.array(external_exports.string()).min(2),
|
|
5987
|
-
references: external_exports.array(
|
|
4323
|
+
var WitanAttestationStatementSchema = external_exports.object({
|
|
4324
|
+
_type: external_exports.literal(WITAN_ATTESTATION_STATEMENT_TYPE),
|
|
4325
|
+
subject: external_exports.array(
|
|
5988
4326
|
external_exports.object({
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
})
|
|
6020
|
-
|
|
6021
|
-
id: external_exports.string().uuid(),
|
|
6022
|
-
studioId: external_exports.string().uuid(),
|
|
6023
|
-
productId: external_exports.string().uuid().nullable(),
|
|
6024
|
-
kind: external_exports.string(),
|
|
6025
|
-
oauthTokenEncrypted: external_exports.string().optional(),
|
|
6026
|
-
refreshTokenEncrypted: external_exports.string().optional(),
|
|
6027
|
-
status: external_exports.enum(["active", "broken", "revoked"]),
|
|
6028
|
-
lastSyncAt: external_exports.coerce.date().optional(),
|
|
6029
|
-
errorCount: external_exports.number().int().nonnegative().default(0)
|
|
6030
|
-
});
|
|
6031
|
-
var EmailAccountSchema = external_exports.object({
|
|
6032
|
-
id: external_exports.string().uuid(),
|
|
6033
|
-
studioId: external_exports.string().uuid(),
|
|
6034
|
-
provider: external_exports.enum(["gmail", "m365", "imap"]),
|
|
6035
|
-
oauthTokenEncrypted: external_exports.string().optional(),
|
|
6036
|
-
defaultLabelPrefix: external_exports.string().optional(),
|
|
6037
|
-
triageCadenceMins: external_exports.number().int().positive().default(240)
|
|
6038
|
-
});
|
|
6039
|
-
var RoutineSchema = external_exports.object({
|
|
6040
|
-
id: external_exports.string().uuid(),
|
|
6041
|
-
productId: external_exports.string().uuid().nullable(),
|
|
6042
|
-
name: external_exports.string(),
|
|
6043
|
-
cronExpression: external_exports.string(),
|
|
6044
|
-
promptTemplate: external_exports.string(),
|
|
6045
|
-
model: external_exports.enum(["sonnet", "opus", "haiku"]).default("sonnet"),
|
|
6046
|
-
lastRunAt: external_exports.coerce.date().optional(),
|
|
6047
|
-
nextRunAt: external_exports.coerce.date().optional(),
|
|
6048
|
-
enabled: external_exports.boolean().default(true),
|
|
6049
|
-
retryCount: external_exports.number().int().nonnegative().default(0)
|
|
6050
|
-
});
|
|
6051
|
-
var RoutineRunSchema = external_exports.object({
|
|
6052
|
-
id: external_exports.string().uuid(),
|
|
6053
|
-
routineId: external_exports.string().uuid(),
|
|
6054
|
-
startedAt: external_exports.coerce.date(),
|
|
6055
|
-
completedAt: external_exports.coerce.date().optional(),
|
|
6056
|
-
status: external_exports.enum(["success", "failed", "retried"]),
|
|
6057
|
-
outputBriefId: external_exports.string().uuid().optional(),
|
|
6058
|
-
errorMessage: external_exports.string().optional(),
|
|
6059
|
-
inferenceCostCents: external_exports.number().int().nonnegative().default(0)
|
|
6060
|
-
});
|
|
6061
|
-
var BriefSchema = external_exports.object({
|
|
6062
|
-
id: external_exports.string().uuid(),
|
|
6063
|
-
studioId: external_exports.string().uuid(),
|
|
6064
|
-
generatedAt: external_exports.coerce.date(),
|
|
6065
|
-
type: external_exports.enum(["daily", "weekly", "on_demand"]),
|
|
6066
|
-
html: external_exports.string().optional(),
|
|
6067
|
-
markdown: external_exports.string(),
|
|
6068
|
-
sourceLinks: external_exports.array(external_exports.object({ label: external_exports.string(), url: external_exports.string() })).default([]),
|
|
6069
|
-
shared: external_exports.boolean().default(false),
|
|
6070
|
-
shareToken: external_exports.string().optional(),
|
|
6071
|
-
shareExpiresAt: external_exports.coerce.date().optional(),
|
|
6072
|
-
inferenceCostCents: external_exports.number().int().nonnegative().default(0)
|
|
6073
|
-
});
|
|
6074
|
-
var MemoryEntrySchema = external_exports.object({
|
|
6075
|
-
id: external_exports.string().uuid(),
|
|
6076
|
-
productId: external_exports.string().uuid(),
|
|
6077
|
-
kind: external_exports.enum(["decision", "fact", "customer", "status", "pattern", "thread"]),
|
|
6078
|
-
content: external_exports.string(),
|
|
6079
|
-
// embedding stored separately in pgvector; not modelled in API layer
|
|
6080
|
-
createdAt: external_exports.coerce.date(),
|
|
6081
|
-
lastReferencedAt: external_exports.coerce.date().optional(),
|
|
6082
|
-
referenceCount: external_exports.number().int().nonnegative().default(0),
|
|
6083
|
-
pinned: external_exports.boolean().default(false)
|
|
6084
|
-
});
|
|
6085
|
-
var InboxClassificationSchema = external_exports.object({
|
|
6086
|
-
id: external_exports.string().uuid(),
|
|
6087
|
-
emailAccountId: external_exports.string().uuid(),
|
|
6088
|
-
productId: external_exports.string().uuid().nullable(),
|
|
6089
|
-
messageId: external_exports.string(),
|
|
6090
|
-
sender: external_exports.string(),
|
|
6091
|
-
labelApplied: external_exports.string(),
|
|
6092
|
-
urgency: external_exports.enum(["needs_reply", "fyi", "noise", "escalation"]),
|
|
6093
|
-
confidence: external_exports.number().min(0).max(1),
|
|
6094
|
-
action: external_exports.enum(["labelled", "archived", "drafted_reply"]),
|
|
6095
|
-
userCorrected: external_exports.boolean().default(false),
|
|
6096
|
-
correctedTo: external_exports.string().optional()
|
|
6097
|
-
});
|
|
6098
|
-
var DraftReplySchema = external_exports.object({
|
|
6099
|
-
id: external_exports.string().uuid(),
|
|
6100
|
-
classificationId: external_exports.string().uuid(),
|
|
6101
|
-
draftText: external_exports.string(),
|
|
6102
|
-
confidence: external_exports.number().min(0).max(1),
|
|
6103
|
-
sentAt: external_exports.coerce.date().optional(),
|
|
6104
|
-
sentVia: external_exports.string().optional()
|
|
6105
|
-
});
|
|
6106
|
-
var AlwaysAlertRuleSchema = external_exports.object({
|
|
6107
|
-
id: external_exports.string().uuid(),
|
|
6108
|
-
studioId: external_exports.string().uuid(),
|
|
6109
|
-
ruleType: external_exports.enum(["sender", "subject", "domain"]),
|
|
6110
|
-
value: external_exports.string(),
|
|
6111
|
-
escalationMethod: external_exports.enum(["push", "slack", "email", "brief_pin"]).default("brief_pin")
|
|
6112
|
-
});
|
|
6113
|
-
var AuditEventSchema = external_exports.object({
|
|
6114
|
-
id: external_exports.string().uuid(),
|
|
6115
|
-
studioId: external_exports.string().uuid(),
|
|
6116
|
-
actor: external_exports.enum(["user", "agent", "system"]),
|
|
6117
|
-
action: external_exports.string(),
|
|
6118
|
-
integrationId: external_exports.string().uuid().optional(),
|
|
6119
|
-
productId: external_exports.string().uuid().optional(),
|
|
6120
|
-
timestamp: external_exports.coerce.date(),
|
|
6121
|
-
metadata: external_exports.record(external_exports.unknown()).default({})
|
|
6122
|
-
});
|
|
6123
|
-
var SubscriptionSchema = external_exports.object({
|
|
6124
|
-
id: external_exports.string().uuid(),
|
|
6125
|
-
studioId: external_exports.string().uuid(),
|
|
6126
|
-
stripeSubscriptionId: external_exports.string().optional(),
|
|
6127
|
-
tier: external_exports.enum(["trial", "solo", "studio", "studio_plus", "self_hosted", "enterprise"]),
|
|
6128
|
-
seats: external_exports.number().int().positive(),
|
|
6129
|
-
status: external_exports.string(),
|
|
6130
|
-
currentPeriodEnd: external_exports.coerce.date(),
|
|
6131
|
-
cancelAt: external_exports.coerce.date().optional()
|
|
6132
|
-
});
|
|
6133
|
-
var ProductMembershipSchema = external_exports.object({
|
|
6134
|
-
humanId: external_exports.string().uuid(),
|
|
6135
|
-
productId: external_exports.string().uuid(),
|
|
6136
|
-
role: external_exports.enum(["lead", "contributor", "observer"])
|
|
6137
|
-
});
|
|
6138
|
-
|
|
6139
|
-
// ../witan/src/batch.ts
|
|
6140
|
-
import { execFileSync as execFileSync3 } from "child_process";
|
|
6141
|
-
import { mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
6142
|
-
import { basename as basename2, join as join5 } from "path";
|
|
6143
|
-
|
|
6144
|
-
// ../witan/src/public-scan.ts
|
|
6145
|
-
import { resolve as resolve2 } from "path";
|
|
6146
|
-
|
|
6147
|
-
// ../witan/src/ingest.ts
|
|
6148
|
-
import { readFileSync as readFileSync5, readdirSync as readdirSync2 } from "fs";
|
|
6149
|
-
import { join as join2 } from "path";
|
|
4327
|
+
name: external_exports.string().min(1).max(300),
|
|
4328
|
+
digest: external_exports.object({
|
|
4329
|
+
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/)
|
|
4330
|
+
}).strict()
|
|
4331
|
+
}).strict()
|
|
4332
|
+
).length(1),
|
|
4333
|
+
predicateType: external_exports.literal(WITAN_ATTESTATION_PREDICATE_TYPE),
|
|
4334
|
+
predicate: external_exports.object({
|
|
4335
|
+
tool: external_exports.object({
|
|
4336
|
+
name: external_exports.literal("cejel"),
|
|
4337
|
+
version: external_exports.string().min(1).max(80)
|
|
4338
|
+
}).strict(),
|
|
4339
|
+
generatedAt: external_exports.string().datetime({ offset: true }),
|
|
4340
|
+
rubricVersion: external_exports.string().min(1).max(120),
|
|
4341
|
+
repository: external_exports.object({
|
|
4342
|
+
productSlug: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/),
|
|
4343
|
+
url: external_exports.string().url().optional(),
|
|
4344
|
+
headSha: external_exports.string().min(7).max(64).optional()
|
|
4345
|
+
}).strict(),
|
|
4346
|
+
report: external_exports.object({
|
|
4347
|
+
artifact: external_exports.literal("report.json"),
|
|
4348
|
+
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/)
|
|
4349
|
+
}).strict(),
|
|
4350
|
+
outcome: WitanAttestationOutcomeSchema,
|
|
4351
|
+
assurance: external_exports.object({
|
|
4352
|
+
status: external_exports.literal("unsigned"),
|
|
4353
|
+
issuer: external_exports.literal("self-generated"),
|
|
4354
|
+
signingHint: external_exports.string().min(1).max(500)
|
|
4355
|
+
}).strict(),
|
|
4356
|
+
limitations: external_exports.array(external_exports.string().min(1).max(500)).min(1).max(8)
|
|
4357
|
+
}).strict()
|
|
4358
|
+
}).strict();
|
|
6150
4359
|
|
|
6151
|
-
//
|
|
6152
|
-
var
|
|
6153
|
-
var
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
function clampFinding(finding) {
|
|
6161
|
-
return {
|
|
6162
|
-
...finding,
|
|
6163
|
-
ruleId: clamp(finding.ruleId, RULE_ID_MAX),
|
|
6164
|
-
message: clamp(finding.message, MESSAGE_MAX),
|
|
6165
|
-
...finding.location ? { location: clamp(finding.location, LOCATION_MAX) } : {}
|
|
6166
|
-
};
|
|
4360
|
+
// src/witan/external-findings.ts
|
|
4361
|
+
var EXTERNAL_FINDINGS_DISPLAY_LIMIT = 10;
|
|
4362
|
+
var SEVERITY_RANK = {
|
|
4363
|
+
critical: 0,
|
|
4364
|
+
warning: 1,
|
|
4365
|
+
info: 2
|
|
4366
|
+
};
|
|
4367
|
+
function formatExternalSourceLabel(source) {
|
|
4368
|
+
return source.startsWith("sarif:") ? source.slice("sarif:".length) : source;
|
|
6167
4369
|
}
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
4370
|
+
function summarizeExternalSources(consumedSignals) {
|
|
4371
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
4372
|
+
for (const signal of consumedSignals) {
|
|
4373
|
+
const entry = bySource.get(signal.source) ?? { findingCount: 0, dimensions: /* @__PURE__ */ new Set() };
|
|
4374
|
+
entry.findingCount += signal.findingCount;
|
|
4375
|
+
entry.dimensions.add(signal.dimension);
|
|
4376
|
+
bySource.set(signal.source, entry);
|
|
4377
|
+
}
|
|
4378
|
+
return Array.from(bySource.entries()).map(([source, { findingCount, dimensions }]) => ({
|
|
4379
|
+
source,
|
|
4380
|
+
label: formatExternalSourceLabel(source),
|
|
4381
|
+
findingCount,
|
|
4382
|
+
dimensions: Array.from(dimensions).sort()
|
|
4383
|
+
})).sort((a, b) => a.source.localeCompare(b.source));
|
|
6175
4384
|
}
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
"A1",
|
|
6180
|
-
"A2",
|
|
6181
|
-
"A3",
|
|
6182
|
-
"A4",
|
|
6183
|
-
"A5",
|
|
6184
|
-
"B1",
|
|
6185
|
-
"B2",
|
|
6186
|
-
"B3",
|
|
6187
|
-
"B4",
|
|
6188
|
-
"B5",
|
|
6189
|
-
"B6"
|
|
6190
|
-
]);
|
|
6191
|
-
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning", "info"]);
|
|
6192
|
-
function isGenericSignalDocument(raw) {
|
|
6193
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
6194
|
-
const doc = raw;
|
|
6195
|
-
return typeof doc.tool === "string" && doc.tool.length > 0 && Array.isArray(doc.signals);
|
|
4385
|
+
function formatExternalSourceLine(summary) {
|
|
4386
|
+
const noun = summary.findingCount === 1 ? "finding" : "findings";
|
|
4387
|
+
return `${summary.label}: ${summary.findingCount} ${noun} ingested (folded into ${summary.dimensions.join(", ")})`;
|
|
6196
4388
|
}
|
|
6197
|
-
function
|
|
6198
|
-
|
|
6199
|
-
const
|
|
6200
|
-
|
|
6201
|
-
for (const signal of raw.signals ?? []) {
|
|
6202
|
-
const dimension = signal.dimension;
|
|
6203
|
-
if (!dimension || !VALID_DIMENSIONS.has(dimension)) continue;
|
|
6204
|
-
const weight = typeof signal.weight === "number" && Number.isFinite(signal.weight) ? Math.min(Math.max(signal.weight, 0), 1) : 0.5;
|
|
6205
|
-
const findings = [];
|
|
6206
|
-
for (const finding of signal.findings ?? []) {
|
|
6207
|
-
const severity = finding.severity;
|
|
6208
|
-
if (!severity || !VALID_SEVERITIES.has(severity)) continue;
|
|
6209
|
-
const ruleId = finding.ruleId ?? "unknown";
|
|
4389
|
+
function collectExternalFindings(consumedSignals) {
|
|
4390
|
+
const findings = [];
|
|
4391
|
+
for (const signal of consumedSignals) {
|
|
4392
|
+
for (const finding of signal.findings) {
|
|
6210
4393
|
findings.push({
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
4394
|
+
source: signal.source,
|
|
4395
|
+
label: formatExternalSourceLabel(signal.source),
|
|
4396
|
+
dimension: signal.dimension,
|
|
4397
|
+
severity: finding.severity,
|
|
4398
|
+
ruleId: finding.ruleId,
|
|
4399
|
+
message: finding.message,
|
|
6214
4400
|
...finding.location ? { location: finding.location } : {}
|
|
6215
4401
|
});
|
|
6216
4402
|
}
|
|
6217
|
-
if (findings.length === 0) continue;
|
|
6218
|
-
signals.push({ source, dimension, weight, findings });
|
|
6219
4403
|
}
|
|
6220
|
-
return
|
|
4404
|
+
return findings.sort((a, b) => {
|
|
4405
|
+
const bySeverity = SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity];
|
|
4406
|
+
if (bySeverity !== 0) return bySeverity;
|
|
4407
|
+
const bySource = a.source.localeCompare(b.source);
|
|
4408
|
+
if (bySource !== 0) return bySource;
|
|
4409
|
+
return a.ruleId.localeCompare(b.ruleId);
|
|
4410
|
+
});
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4413
|
+
// src/witan/html.ts
|
|
4414
|
+
function renderWitanHtmlReport(report) {
|
|
4415
|
+
const codeCriteria = criteriaByCategory(report, "code_trust");
|
|
4416
|
+
const processCriteria = criteriaByCategory(report, "process_trust");
|
|
4417
|
+
const verifiedEvidence = report.criteria.flatMap(
|
|
4418
|
+
(criterion) => criterion.status === "verified" ? criterion.evidence.map((evidence) => renderEvidenceListItem(criterion, evidence)) : []
|
|
4419
|
+
);
|
|
4420
|
+
const openItems = report.criteria.flatMap(renderOpenItems);
|
|
4421
|
+
const contributingSources = renderContributingSources(report.consumedSignals ?? []);
|
|
4422
|
+
const externalSourceSummaries = summarizeExternalSources(report.consumedSignals ?? []);
|
|
4423
|
+
const externalFindings = collectExternalFindings(report.consumedSignals ?? []);
|
|
4424
|
+
return `<!doctype html>
|
|
4425
|
+
<html lang="en">
|
|
4426
|
+
<head>
|
|
4427
|
+
<meta charset="utf-8">
|
|
4428
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
4429
|
+
<title>Cejel Trust Certificate - ${escapeHtml(report.productDisplayName)}</title>
|
|
4430
|
+
<style>${CERTIFICATE_CSS}</style>
|
|
4431
|
+
</head>
|
|
4432
|
+
<body>
|
|
4433
|
+
<main class="certificate">
|
|
4434
|
+
<header class="hero">
|
|
4435
|
+
<div class="brand">
|
|
4436
|
+
<span class="brand-mark" aria-hidden="true">C</span>
|
|
4437
|
+
<span class="brand-name">Cejel</span>
|
|
4438
|
+
</div>
|
|
4439
|
+
<div class="hero-grid">
|
|
4440
|
+
<section>
|
|
4441
|
+
<p class="eyebrow">Trust Certificate</p>
|
|
4442
|
+
<h1>${escapeHtml(report.productDisplayName)}</h1>
|
|
4443
|
+
<dl class="meta">
|
|
4444
|
+
<div><dt>Date</dt><dd>${escapeHtml(formatDate(report.generatedAt))}</dd></div>
|
|
4445
|
+
<div><dt>Run</dt><dd>${escapeHtml(renderRepo(report))}</dd></div>
|
|
4446
|
+
<div><dt>Rubric</dt><dd>${escapeHtml(report.rubricVersion)}</dd></div>
|
|
4447
|
+
${contributingSources.length > 0 ? `<div><dt>Sources</dt><dd>Incorporates findings from: ${escapeHtml(contributingSources.join(", "))}<ul class="source-counts">${externalSourceSummaries.map((s) => `<li>${escapeHtml(formatExternalSourceLine(s))}</li>`).join("")}</ul></dd></div>` : ""}
|
|
4448
|
+
</dl>
|
|
4449
|
+
</section>
|
|
4450
|
+
<aside class="score-panel" aria-label="Summary trust score">
|
|
4451
|
+
<div class="score-badge">Summary</div>
|
|
4452
|
+
${report.verdict === "insufficient_source" ? `<div class="verdict">Insufficient source</div>
|
|
4453
|
+
<p class="insufficient-note">${escapeHtml(report.insufficientSourceReason)}</p>` : `<div class="score">${formatScore(report.overallScore)}</div>
|
|
4454
|
+
<div class="score-unit">/ 4.0 overall</div>
|
|
4455
|
+
<div class="verdict">${escapeHtml(renderVerdict(report.overallScore))}</div>
|
|
4456
|
+
<div class="subscores">
|
|
4457
|
+
<span>Code ${formatScore(report.codeTrustScore)}</span>
|
|
4458
|
+
<span>Process ${formatScore(report.processTrustScore)}</span>
|
|
4459
|
+
</div>`}
|
|
4460
|
+
</aside>
|
|
4461
|
+
</div>
|
|
4462
|
+
</header>
|
|
4463
|
+
|
|
4464
|
+
<section class="trust-grid" aria-label="Rubric criteria">
|
|
4465
|
+
${renderCriterionColumn("Code trust", codeCriteria)}
|
|
4466
|
+
${renderCriterionColumn("Process trust", processCriteria)}
|
|
4467
|
+
</section>
|
|
4468
|
+
|
|
4469
|
+
<section class="evidence-grid" aria-label="Evidence and gaps">
|
|
4470
|
+
<article class="evidence-section">
|
|
4471
|
+
<h2>Verified evidence</h2>
|
|
4472
|
+
<ul>${verifiedEvidence.length > 0 ? verifiedEvidence.join("") : "<li>No verified evidence supplied.</li>"}</ul>
|
|
4473
|
+
</article>
|
|
4474
|
+
<article class="evidence-section">
|
|
4475
|
+
<h2>Open / unverified</h2>
|
|
4476
|
+
<ul>${openItems.length > 0 ? openItems.join("") : "<li>No open or unverified criteria supplied.</li>"}</ul>
|
|
4477
|
+
</article>
|
|
4478
|
+
</section>
|
|
4479
|
+
|
|
4480
|
+
${externalFindings.length > 0 ? `<section class="external-findings-section" aria-label="External findings">
|
|
4481
|
+
<article class="evidence-section">
|
|
4482
|
+
<h2>External findings</h2>
|
|
4483
|
+
<p class="external-note">Findings surfaced by ingested external scanners, attributed to the tool and the cejel criterion they were folded into \u2014 distinct from cejel's own findings above.</p>
|
|
4484
|
+
<ul>${renderExternalFindingItems(externalFindings).join("")}</ul>
|
|
4485
|
+
</article>
|
|
4486
|
+
</section>` : ""}
|
|
4487
|
+
</main>
|
|
4488
|
+
</body>
|
|
4489
|
+
</html>
|
|
4490
|
+
`;
|
|
4491
|
+
}
|
|
4492
|
+
function renderContributingSources(signals) {
|
|
4493
|
+
return Array.from(new Set(signals.map((s) => s.source))).sort();
|
|
4494
|
+
}
|
|
4495
|
+
function renderExternalFindingItems(findings) {
|
|
4496
|
+
const shown = findings.slice(0, EXTERNAL_FINDINGS_DISPLAY_LIMIT);
|
|
4497
|
+
const items = shown.map(
|
|
4498
|
+
(f) => `<li><strong>${escapeHtml(f.label)} \u2192 ${escapeHtml(f.dimension)}</strong><span>${escapeHtml(f.severity)}: ${escapeHtml(f.ruleId)} \u2014 ${escapeHtml(f.message)}${f.location ? ` (${escapeHtml(f.location)})` : ""}</span></li>`
|
|
4499
|
+
);
|
|
4500
|
+
const remaining = findings.length - shown.length;
|
|
4501
|
+
if (remaining > 0) {
|
|
4502
|
+
items.push(`<li><em>...and ${remaining} more \u2014 see report.json for the full list.</em></li>`);
|
|
4503
|
+
}
|
|
4504
|
+
return items;
|
|
4505
|
+
}
|
|
4506
|
+
function criteriaByCategory(report, category) {
|
|
4507
|
+
return report.criteria.filter((criterion) => criterion.category === category);
|
|
4508
|
+
}
|
|
4509
|
+
function renderCriterionColumn(title, criteria) {
|
|
4510
|
+
const applicable = criteria.filter((criterion) => criterion.status !== "not_applicable");
|
|
4511
|
+
const notApplicable = criteria.filter((criterion) => criterion.status === "not_applicable");
|
|
4512
|
+
return `<section class="criteria-column">
|
|
4513
|
+
<h2>${escapeHtml(title)}</h2>
|
|
4514
|
+
<div class="criteria-list">
|
|
4515
|
+
${applicable.map(renderCriterionCard).join("")}
|
|
4516
|
+
</div>
|
|
4517
|
+
${notApplicable.length > 0 ? renderNotApplicableGroup(notApplicable) : ""}
|
|
4518
|
+
</section>`;
|
|
4519
|
+
}
|
|
4520
|
+
function renderNotApplicableGroup(criteria) {
|
|
4521
|
+
return `<div class="na-group">
|
|
4522
|
+
<h3 class="na-heading">Not applicable to this repository</h3>
|
|
4523
|
+
<ul class="na-list">
|
|
4524
|
+
${criteria.map(renderNotApplicableItem).join("")}
|
|
4525
|
+
</ul>
|
|
4526
|
+
</div>`;
|
|
4527
|
+
}
|
|
4528
|
+
function renderNotApplicableItem(criterion) {
|
|
4529
|
+
const reason = criterion.notes ?? "Not applicable to this repository.";
|
|
4530
|
+
return `<li><span class="na-id">${escapeHtml(criterion.id)}</span> ${escapeHtml(criterion.title)} \u2014 <span class="na-reason">${escapeHtml(reason)}</span></li>`;
|
|
4531
|
+
}
|
|
4532
|
+
function renderCriterionCard(criterion) {
|
|
4533
|
+
const evidence = [
|
|
4534
|
+
...criterion.evidence.map(renderEvidencePointer),
|
|
4535
|
+
...criterion.findings.map((finding) => renderFindingEvidence(finding))
|
|
4536
|
+
];
|
|
4537
|
+
const metrics = criterion.metrics.map(renderMetric);
|
|
4538
|
+
return `<article class="criterion">
|
|
4539
|
+
<div class="criterion-top">
|
|
4540
|
+
<div>
|
|
4541
|
+
<div class="criterion-id">${escapeHtml(criterion.id)}</div>
|
|
4542
|
+
<h3>${escapeHtml(criterion.title)}</h3>
|
|
4543
|
+
</div>
|
|
4544
|
+
${renderStatusChip(criterion.status)}
|
|
4545
|
+
</div>
|
|
4546
|
+
<div class="criterion-score">${criterion.status === "not_applicable" ? "N/A" : criterion.status === "insufficient_data" ? "No data" : formatScore(criterion.score)}</div>
|
|
4547
|
+
<ul class="criterion-metrics">
|
|
4548
|
+
${metrics.length > 0 ? metrics.map((item) => `<li>${item}</li>`).join("") : "<li>No measured depth metrics supplied.</li>"}
|
|
4549
|
+
</ul>
|
|
4550
|
+
<ul class="criterion-evidence">
|
|
4551
|
+
${evidence.length > 0 ? evidence.map((item) => `<li>${item}</li>`).join("") : "<li>No concrete evidence supplied.</li>"}
|
|
4552
|
+
</ul>
|
|
4553
|
+
</article>`;
|
|
4554
|
+
}
|
|
4555
|
+
function renderMetric(metric2) {
|
|
4556
|
+
const max = metric2.max ? `/${formatMetricValue(metric2.max)}` : "";
|
|
4557
|
+
const unit = metric2.unit ? ` ${escapeHtml(metric2.unit)}` : "";
|
|
4558
|
+
return `<strong>${escapeHtml(metric2.label)}</strong><span>${formatMetricValue(metric2.value)}${max}${unit}</span>`;
|
|
4559
|
+
}
|
|
4560
|
+
function renderStatusChip(status) {
|
|
4561
|
+
return `<span class="status" data-status="${status}">${status}</span>`;
|
|
4562
|
+
}
|
|
4563
|
+
function renderEvidenceListItem(criterion, evidence) {
|
|
4564
|
+
return `<li><strong>${escapeHtml(criterion.id)} - ${escapeHtml(criterion.title)}</strong><span>${renderEvidencePointer(evidence)}</span></li>`;
|
|
4565
|
+
}
|
|
4566
|
+
function renderOpenItems(criterion) {
|
|
4567
|
+
const findingItems = criterion.findings.map(
|
|
4568
|
+
(finding) => `<li><strong>${escapeHtml(criterion.id)} - ${escapeHtml(criterion.title)}</strong><span>${escapeHtml(finding.severity)}: ${escapeHtml(finding.summary)} (${renderEvidencePointer(finding.evidence)})</span></li>`
|
|
4569
|
+
);
|
|
4570
|
+
if ((criterion.status === "unverified" || criterion.status === "insufficient_data") && criterion.evidence.length === 0 && criterion.findings.length === 0) {
|
|
4571
|
+
const message = criterion.status === "insufficient_data" ? "Insufficient data \u2014 no measurable signal; excluded from composite (unmeasured, not inapplicable)." : "No concrete evidence supplied.";
|
|
4572
|
+
return [
|
|
4573
|
+
`<li><strong>${escapeHtml(criterion.id)} - ${escapeHtml(criterion.title)}</strong><span>${escapeHtml(message)}</span></li>`
|
|
4574
|
+
];
|
|
4575
|
+
}
|
|
4576
|
+
if (criterion.status === "verified") return [];
|
|
4577
|
+
return findingItems;
|
|
6221
4578
|
}
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
// A2 — injection / secrets / auth (high weight)
|
|
6227
|
-
{
|
|
6228
|
-
pattern: /sql[- _]?inject|cwe-89|sqli|command[- _]?inject|cwe-78|os[- _]?cmd|rce|remote[- _]?code/i,
|
|
6229
|
-
dimension: "A2",
|
|
6230
|
-
weight: 0.9
|
|
6231
|
-
},
|
|
6232
|
-
{
|
|
6233
|
-
pattern: /secret|credential|api[- _]?key|password[- _]?leak|hardcoded[- _]?(token|key|secret)|cwe-259|cwe-798/i,
|
|
6234
|
-
dimension: "A2",
|
|
6235
|
-
weight: 0.9
|
|
6236
|
-
},
|
|
6237
|
-
{
|
|
6238
|
-
pattern: /path[- _]?traversal|directory[- _]?traversal|cwe-22|lfi|rfi/i,
|
|
6239
|
-
dimension: "A2",
|
|
6240
|
-
weight: 0.8
|
|
6241
|
-
},
|
|
6242
|
-
{
|
|
6243
|
-
pattern: /ssrf|server[- _]?side[- _]?request[- _]?forg|cwe-918/i,
|
|
6244
|
-
dimension: "A2",
|
|
6245
|
-
weight: 0.8
|
|
6246
|
-
},
|
|
6247
|
-
{
|
|
6248
|
-
pattern: /xxe|xml[- _]?external[- _]?entity|cwe-611/i,
|
|
6249
|
-
dimension: "A2",
|
|
6250
|
-
weight: 0.8
|
|
6251
|
-
},
|
|
6252
|
-
{
|
|
6253
|
-
pattern: /auth[- _]?bypass|broken[- _]?auth|missing[- _]?auth|cwe-287|cwe-306|cwe-863|cwe-862/i,
|
|
6254
|
-
dimension: "A2",
|
|
6255
|
-
weight: 0.7
|
|
6256
|
-
},
|
|
6257
|
-
{
|
|
6258
|
-
pattern: /xss|cross[- _]?site[- _]?script|cwe-79/i,
|
|
6259
|
-
dimension: "A2",
|
|
6260
|
-
weight: 0.6
|
|
6261
|
-
},
|
|
6262
|
-
// A4 — dependency vulnerabilities
|
|
6263
|
-
{
|
|
6264
|
-
pattern: /cve-\d{4}-\d+|supply[- _]?chain|depend[a-z]*[- _]?vulner|outdated[- _]?depend|deprecated[- _]?package/i,
|
|
6265
|
-
dimension: "A4",
|
|
6266
|
-
weight: 0.8
|
|
6267
|
-
},
|
|
6268
|
-
{
|
|
6269
|
-
pattern: /npm[- _]?audit|yarn[- _]?audit|pnpm[- _]?audit|pip[- _]?audit|cargo[- _]?audit/i,
|
|
6270
|
-
dimension: "A4",
|
|
6271
|
-
weight: 0.7
|
|
6272
|
-
},
|
|
6273
|
-
// A3 — production readiness / insecure config
|
|
6274
|
-
{
|
|
6275
|
-
pattern: /insecure[- _]?tls|weak[- _]?cipher|tls[- _]?version|http[- _]?strict|hsts|csp[- _]?missing|cwe-326|cwe-327/i,
|
|
6276
|
-
dimension: "A3",
|
|
6277
|
-
weight: 0.5
|
|
6278
|
-
},
|
|
6279
|
-
{
|
|
6280
|
-
pattern: /error[- _]?handl|unhandled[- _]?exception|crash|uncaught|stacktrace[- _]?leak/i,
|
|
6281
|
-
dimension: "A3",
|
|
6282
|
-
weight: 0.4
|
|
6283
|
-
},
|
|
6284
|
-
{
|
|
6285
|
-
pattern: /debug[- _]?mode|dev[- _]?endpoint|staging[- _]?secret/i,
|
|
6286
|
-
dimension: "A3",
|
|
6287
|
-
weight: 0.4
|
|
6288
|
-
},
|
|
6289
|
-
// A1 — test integrity (low weight; SARIF rarely surfaces this)
|
|
6290
|
-
{
|
|
6291
|
-
pattern: /skipped[- _]?test|hollow[- _]?test|empty[- _]?assert|no[- _]?assertion/i,
|
|
6292
|
-
dimension: "A1",
|
|
6293
|
-
weight: 0.2
|
|
6294
|
-
}
|
|
6295
|
-
];
|
|
6296
|
-
var DEFAULT_DIMENSION = "A2";
|
|
6297
|
-
var DEFAULT_WEIGHT = 0.3;
|
|
6298
|
-
var DROP_LEVEL = /* @__PURE__ */ new Set(["none"]);
|
|
6299
|
-
function mapLevel(level) {
|
|
6300
|
-
if (!level || DROP_LEVEL.has(level)) return null;
|
|
6301
|
-
if (level === "error") return "critical";
|
|
6302
|
-
if (level === "warning") return "warning";
|
|
6303
|
-
return "info";
|
|
4579
|
+
function renderFindingEvidence(finding) {
|
|
4580
|
+
return `${escapeHtml(finding.severity)}: ${escapeHtml(finding.summary)} (${renderEvidencePointer(
|
|
4581
|
+
finding.evidence
|
|
4582
|
+
)})`;
|
|
6304
4583
|
}
|
|
6305
|
-
function
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
}
|
|
4584
|
+
function renderEvidencePointer(evidence) {
|
|
4585
|
+
const target = evidence.url ?? renderPathEvidenceTarget(evidence);
|
|
4586
|
+
const label = escapeHtml(evidence.label);
|
|
4587
|
+
if (evidence.url) {
|
|
4588
|
+
return `<a href="${escapeAttribute(evidence.url)}">${label}</a>`;
|
|
6310
4589
|
}
|
|
6311
|
-
return {
|
|
4590
|
+
return [label, target ? `<code>${escapeHtml(target)}</code>` : void 0].filter(Boolean).join(" ");
|
|
6312
4591
|
}
|
|
6313
|
-
function
|
|
6314
|
-
const
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
const line = loc.region?.startLine;
|
|
6318
|
-
if (!uri) return void 0;
|
|
6319
|
-
return line != null ? `${uri}:${line}` : uri;
|
|
4592
|
+
function renderPathEvidenceTarget(evidence) {
|
|
4593
|
+
const pathTarget = evidence.path ? `${evidence.path}${evidence.line ? `:${evidence.line}` : ""}` : void 0;
|
|
4594
|
+
const hashTarget = evidence.contentHash ? `sha256:${evidence.contentHash.slice(0, 12)}` : void 0;
|
|
4595
|
+
return [pathTarget, hashTarget].filter(Boolean).join(" \xB7 ");
|
|
6320
4596
|
}
|
|
6321
|
-
function
|
|
6322
|
-
const
|
|
6323
|
-
return
|
|
6324
|
-
const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
|
|
6325
|
-
if (seen.has(key)) return false;
|
|
6326
|
-
seen.add(key);
|
|
6327
|
-
return true;
|
|
6328
|
-
});
|
|
4597
|
+
function renderRepo(report) {
|
|
4598
|
+
const repo = report.repo.path ?? report.repo.url ?? "unknown";
|
|
4599
|
+
return report.repo.headSha ? `${repo} @ ${report.repo.headSha}` : repo;
|
|
6329
4600
|
}
|
|
6330
|
-
function
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
const severity = mapLevel(effectiveLevel);
|
|
6349
|
-
if (!severity) continue;
|
|
6350
|
-
const message = result.message?.text ?? ruleId;
|
|
6351
|
-
const location = renderLocation(result);
|
|
6352
|
-
const { dimension, weight } = mapRuleToDimension(ruleId, dimensionRules);
|
|
6353
|
-
const bucketKey = `${source}|${dimension}`;
|
|
6354
|
-
if (!buckets.has(bucketKey)) {
|
|
6355
|
-
buckets.set(bucketKey, { source, dimension, weight, findings: [] });
|
|
6356
|
-
}
|
|
6357
|
-
buckets.get(bucketKey)?.findings.push({ ruleId, severity, message, ...location ? { location } : {} });
|
|
6358
|
-
}
|
|
4601
|
+
function renderVerdict(score) {
|
|
4602
|
+
return renderMachineVerdict(witanVerdictForScore(score));
|
|
4603
|
+
}
|
|
4604
|
+
function renderReportVerdict(report) {
|
|
4605
|
+
return renderMachineVerdict(report.verdict);
|
|
4606
|
+
}
|
|
4607
|
+
function renderMachineVerdict(verdict) {
|
|
4608
|
+
switch (verdict) {
|
|
4609
|
+
case "verified":
|
|
4610
|
+
return "Verified";
|
|
4611
|
+
case "conditional":
|
|
4612
|
+
return "Conditional";
|
|
4613
|
+
case "at_risk":
|
|
4614
|
+
return "At risk";
|
|
4615
|
+
case "unverified":
|
|
4616
|
+
return "Unverified";
|
|
4617
|
+
case "insufficient_source":
|
|
4618
|
+
return "Insufficient source";
|
|
6359
4619
|
}
|
|
6360
|
-
return Array.from(buckets.values()).map(({ source, dimension, weight, findings }) => ({
|
|
6361
|
-
source,
|
|
6362
|
-
dimension,
|
|
6363
|
-
weight,
|
|
6364
|
-
findings: dedupeFindings(findings)
|
|
6365
|
-
}));
|
|
6366
4620
|
}
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
"
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
4621
|
+
function formatScore(score) {
|
|
4622
|
+
return score.toFixed(1);
|
|
4623
|
+
}
|
|
4624
|
+
function formatMetricValue(value) {
|
|
4625
|
+
return Number.isInteger(value) ? value.toString() : value.toFixed(2);
|
|
4626
|
+
}
|
|
4627
|
+
function formatDate(value) {
|
|
4628
|
+
return value.slice(0, 10);
|
|
4629
|
+
}
|
|
4630
|
+
function escapeHtml(value) {
|
|
4631
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4632
|
+
}
|
|
4633
|
+
function escapeAttribute(value) {
|
|
4634
|
+
return escapeHtml(value);
|
|
4635
|
+
}
|
|
4636
|
+
var CERTIFICATE_CSS = `
|
|
4637
|
+
:root {
|
|
4638
|
+
color-scheme: dark;
|
|
4639
|
+
--steel: #16212a;
|
|
4640
|
+
--surface: #1d2b35;
|
|
4641
|
+
--surface-2: #273946;
|
|
4642
|
+
--line: rgba(238, 244, 247, .13);
|
|
4643
|
+
--line-strong: rgba(238, 244, 247, .22);
|
|
4644
|
+
--text: #eef4f7;
|
|
4645
|
+
--muted: #b7c5cc;
|
|
4646
|
+
--faint: #8799a4;
|
|
4647
|
+
--teal: #2fc8a6;
|
|
4648
|
+
--teal-weak: rgba(47, 200, 166, .14);
|
|
4649
|
+
--periwinkle: #93a6da;
|
|
4650
|
+
--periwinkle-weak: rgba(147, 166, 218, .16);
|
|
4651
|
+
--warn: #e7bf72;
|
|
4652
|
+
--warn-weak: rgba(231, 191, 114, .16);
|
|
4653
|
+
--danger: #f09a8f;
|
|
4654
|
+
--danger-weak: rgba(240, 154, 143, .14);
|
|
4655
|
+
--quiet: rgba(238, 244, 247, .08);
|
|
4656
|
+
--serif: "Instrument Serif", Georgia, "Times New Roman", serif;
|
|
4657
|
+
--sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
4658
|
+
--mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
4659
|
+
}
|
|
4660
|
+
* { box-sizing: border-box; }
|
|
4661
|
+
body {
|
|
4662
|
+
margin: 0;
|
|
4663
|
+
background: var(--steel);
|
|
4664
|
+
color: var(--text);
|
|
4665
|
+
font-family: var(--sans);
|
|
4666
|
+
line-height: 1.55;
|
|
4667
|
+
-webkit-font-smoothing: antialiased;
|
|
4668
|
+
}
|
|
4669
|
+
.certificate { max-width: 1120px; margin: 0 auto; padding: 44px 32px 64px; }
|
|
4670
|
+
.hero { border-bottom: 1px solid var(--line); padding-bottom: 38px; }
|
|
4671
|
+
.brand { display: flex; align-items: center; gap: 12px; margin-bottom: 44px; }
|
|
4672
|
+
.brand-mark {
|
|
4673
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
4674
|
+
width: 34px; height: 34px; border-radius: 8px;
|
|
4675
|
+
background: var(--teal); color: #06231d; font-family: var(--serif); font-size: 24px;
|
|
4676
|
+
}
|
|
4677
|
+
.brand-name { font-family: var(--serif); font-size: 24px; }
|
|
4678
|
+
.hero-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 36px; align-items: end; }
|
|
4679
|
+
.eyebrow {
|
|
4680
|
+
margin: 0 0 14px; color: var(--teal); font-family: var(--mono);
|
|
4681
|
+
font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
|
|
6400
4682
|
}
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
4683
|
+
h1, h2, h3, p { margin-top: 0; }
|
|
4684
|
+
h1 { margin-bottom: 24px; font-family: var(--serif); font-size: 64px; line-height: 1; font-weight: 400; letter-spacing: 0; }
|
|
4685
|
+
.meta { display: grid; gap: 10px; margin: 0; max-width: 780px; }
|
|
4686
|
+
.meta div { display: grid; grid-template-columns: 86px minmax(0, 1fr); gap: 16px; }
|
|
4687
|
+
dt { color: var(--faint); font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: .12em; }
|
|
4688
|
+
dd { margin: 0; color: var(--muted); overflow-wrap: anywhere; }
|
|
4689
|
+
.score-panel { border: 1px solid var(--line-strong); border-radius: 8px; padding: 24px; background: var(--surface); }
|
|
4690
|
+
.score-badge {
|
|
4691
|
+
display: inline-flex; margin-bottom: 14px; border: 1px solid rgba(147, 166, 218, .38);
|
|
4692
|
+
border-radius: 999px; padding: 5px 10px; color: var(--periwinkle);
|
|
4693
|
+
background: var(--periwinkle-weak); font-family: var(--mono); font-size: 12px;
|
|
6409
4694
|
}
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
4695
|
+
.score { display: inline; font-family: var(--mono); font-size: 56px; line-height: 1; color: var(--teal); }
|
|
4696
|
+
.score-unit { display: inline; margin-left: 6px; color: var(--faint); font-family: var(--mono); }
|
|
4697
|
+
.verdict { margin-top: 12px; font-family: var(--serif); font-size: 30px; color: var(--periwinkle); }
|
|
4698
|
+
.insufficient-note { margin-top: 10px; color: var(--muted); font-size: 13px; line-height: 1.5; }
|
|
4699
|
+
.subscores { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 18px; color: var(--muted); font-family: var(--mono); font-size: 12px; }
|
|
4700
|
+
.source-counts { margin: 8px 0 0; padding-left: 18px; font-family: var(--mono); font-size: 12px; color: var(--muted); }
|
|
4701
|
+
.trust-grid, .evidence-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; margin-top: 28px; }
|
|
4702
|
+
.external-findings-section { margin-top: 18px; }
|
|
4703
|
+
.external-note { margin: 0 0 14px; color: var(--muted); font-size: 13px; }
|
|
4704
|
+
.criteria-column, .evidence-section { border: 1px solid var(--line); border-radius: 8px; background: var(--surface); padding: 22px; }
|
|
4705
|
+
h2 { font-family: var(--serif); font-size: 30px; font-weight: 400; letter-spacing: 0; margin-bottom: 18px; }
|
|
4706
|
+
.criteria-list { display: grid; gap: 12px; }
|
|
4707
|
+
.na-group { margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--line-strong); }
|
|
4708
|
+
.na-heading { font-family: var(--sans); font-size: 12px; font-weight: 650; letter-spacing: .04em; text-transform: uppercase; color: var(--faint); margin: 0 0 10px; }
|
|
4709
|
+
.na-list { display: grid; gap: 8px; font-size: 13px; }
|
|
4710
|
+
.na-list li { margin: 0; color: var(--muted); }
|
|
4711
|
+
.na-id { color: var(--faint); font-family: var(--mono); font-size: 11px; margin-right: 6px; }
|
|
4712
|
+
.na-reason { color: var(--muted); }
|
|
4713
|
+
.criterion { border: 1px solid var(--line); border-radius: 8px; padding: 16px; background: var(--surface-2); }
|
|
4714
|
+
.criterion-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; }
|
|
4715
|
+
.criterion-id { color: var(--periwinkle); font-family: var(--mono); font-size: 12px; margin-bottom: 4px; }
|
|
4716
|
+
h3 { font-size: 15px; line-height: 1.35; font-weight: 600; margin-bottom: 0; }
|
|
4717
|
+
.criterion-score { margin-top: 12px; color: var(--text); font-family: var(--mono); font-size: 24px; }
|
|
4718
|
+
.criterion-metrics { display: grid; gap: 7px; margin-top: 10px; padding: 0; list-style: none; font-size: 12px; }
|
|
4719
|
+
.criterion-metrics li { display: flex; justify-content: space-between; gap: 12px; border-bottom: 1px solid rgba(238, 244, 247, .08); padding-bottom: 6px; }
|
|
4720
|
+
.criterion-metrics strong { color: var(--text); font-weight: 650; }
|
|
4721
|
+
.criterion-metrics span { white-space: nowrap; color: var(--muted); }
|
|
4722
|
+
.status { flex: none; border-radius: 999px; padding: 4px 9px; font-family: var(--mono); font-size: 11px; border: 1px solid var(--line-strong); }
|
|
4723
|
+
.status[data-status="verified"] { color: var(--teal); background: var(--teal-weak); border-color: rgba(47, 200, 166, .42); }
|
|
4724
|
+
.status[data-status="info"] { color: var(--periwinkle); background: var(--periwinkle-weak); border-color: rgba(147, 166, 218, .4); }
|
|
4725
|
+
.status[data-status="warning"] { color: var(--warn); background: var(--warn-weak); border-color: rgba(231, 191, 114, .44); }
|
|
4726
|
+
.status[data-status="critical"] { color: var(--danger); background: var(--danger-weak); border-color: rgba(240, 154, 143, .46); }
|
|
4727
|
+
.status[data-status="unverified"] { color: var(--muted); background: var(--quiet); }
|
|
4728
|
+
.status[data-status="insufficient_data"] { color: var(--muted); background: var(--quiet); border-style: dashed; }
|
|
4729
|
+
ul { margin: 0; padding-left: 18px; }
|
|
4730
|
+
li { margin: 8px 0; color: var(--muted); }
|
|
4731
|
+
.criterion-evidence { margin-top: 12px; font-size: 13px; }
|
|
4732
|
+
.evidence-section li strong { display: block; color: var(--text); font-size: 14px; }
|
|
4733
|
+
.evidence-section li span { display: block; margin-top: 2px; font-size: 13px; }
|
|
4734
|
+
code { color: var(--periwinkle); font-family: var(--mono); font-size: .92em; overflow-wrap: anywhere; }
|
|
4735
|
+
a { color: var(--teal); text-decoration: none; }
|
|
4736
|
+
a:hover { text-decoration: underline; text-underline-offset: 2px; }
|
|
4737
|
+
@media (max-width: 840px) {
|
|
4738
|
+
.certificate { padding: 28px 18px 48px; }
|
|
4739
|
+
.hero-grid, .trust-grid, .evidence-grid { grid-template-columns: 1fr; }
|
|
4740
|
+
h1 { font-size: 46px; }
|
|
6441
4741
|
}
|
|
4742
|
+
`;
|
|
6442
4743
|
|
|
6443
|
-
//
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
4744
|
+
// src/witan/badge.ts
|
|
4745
|
+
var VERDICT_COLOR = {
|
|
4746
|
+
Verified: "brightgreen",
|
|
4747
|
+
Conditional: "yellow",
|
|
4748
|
+
"At risk": "orange",
|
|
4749
|
+
Unverified: "red",
|
|
4750
|
+
"Insufficient source": "lightgrey"
|
|
4751
|
+
};
|
|
4752
|
+
var VERDICT_SVG_FILL = {
|
|
4753
|
+
Verified: "#2fc86a",
|
|
4754
|
+
Conditional: "#dfb92f",
|
|
4755
|
+
"At risk": "#e08a3c",
|
|
4756
|
+
Unverified: "#d64545",
|
|
4757
|
+
"Insufficient source": "#8c8c8c"
|
|
4758
|
+
};
|
|
4759
|
+
function badgeMessage(report, verdict) {
|
|
4760
|
+
if (report.verdict === "insufficient_source") return "unrated: no source";
|
|
4761
|
+
return `${formatScore2(report.overallScore)}/4.0 ${verdict.toLowerCase()}`;
|
|
6447
4762
|
}
|
|
6448
|
-
function
|
|
6449
|
-
|
|
6450
|
-
return
|
|
4763
|
+
function renderWitanBadgeEndpoint(report) {
|
|
4764
|
+
const verdict = renderReportVerdict(report);
|
|
4765
|
+
return {
|
|
4766
|
+
schemaVersion: 1,
|
|
4767
|
+
label: "cejel trust",
|
|
4768
|
+
message: badgeMessage(report, verdict),
|
|
4769
|
+
color: VERDICT_COLOR[verdict] ?? "lightgrey"
|
|
4770
|
+
};
|
|
6451
4771
|
}
|
|
6452
|
-
function
|
|
6453
|
-
const
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
4772
|
+
function renderWitanBadgeSvg(report) {
|
|
4773
|
+
const verdict = renderReportVerdict(report);
|
|
4774
|
+
const label = "cejel trust";
|
|
4775
|
+
const message = badgeMessage(report, verdict);
|
|
4776
|
+
const fill = VERDICT_SVG_FILL[verdict] ?? "#8c8c8c";
|
|
4777
|
+
const charWidth = 6.5;
|
|
4778
|
+
const padding = 10;
|
|
4779
|
+
const labelWidth = Math.round(label.length * charWidth + padding);
|
|
4780
|
+
const messageWidth = Math.round(message.length * charWidth + padding);
|
|
4781
|
+
const totalWidth = labelWidth + messageWidth;
|
|
4782
|
+
const height = 20;
|
|
4783
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="${height}" role="img" aria-label="${escapeXml(label)}: ${escapeXml(message)}">
|
|
4784
|
+
<title>${escapeXml(label)}: ${escapeXml(message)}</title>
|
|
4785
|
+
<linearGradient id="witan-badge-smooth" x2="0" y2="100%">
|
|
4786
|
+
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
|
4787
|
+
<stop offset="1" stop-opacity=".1"/>
|
|
4788
|
+
</linearGradient>
|
|
4789
|
+
<clipPath id="witan-badge-round">
|
|
4790
|
+
<rect width="${totalWidth}" height="${height}" rx="3" fill="#fff"/>
|
|
4791
|
+
</clipPath>
|
|
4792
|
+
<g clip-path="url(#witan-badge-round)">
|
|
4793
|
+
<rect width="${labelWidth}" height="${height}" fill="#555"/>
|
|
4794
|
+
<rect x="${labelWidth}" width="${messageWidth}" height="${height}" fill="${fill}"/>
|
|
4795
|
+
<rect width="${totalWidth}" height="${height}" fill="url(#witan-badge-smooth)"/>
|
|
4796
|
+
</g>
|
|
4797
|
+
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="11">
|
|
4798
|
+
<text x="${labelWidth / 2}" y="14">${escapeXml(label)}</text>
|
|
4799
|
+
<text x="${labelWidth + messageWidth / 2}" y="14">${escapeXml(message)}</text>
|
|
4800
|
+
</g>
|
|
4801
|
+
</svg>
|
|
4802
|
+
`;
|
|
6468
4803
|
}
|
|
6469
|
-
function
|
|
6470
|
-
|
|
6471
|
-
if (Array.isArray(obj.runs)) {
|
|
6472
|
-
const firstRun = obj.runs[0];
|
|
6473
|
-
return firstRun?.tool?.driver?.name ?? "unknown";
|
|
6474
|
-
}
|
|
6475
|
-
if (typeof obj.tool === "string" && obj.tool.length > 0) return obj.tool;
|
|
6476
|
-
return "scorecard";
|
|
4804
|
+
function formatScore2(score) {
|
|
4805
|
+
return score.toFixed(1);
|
|
6477
4806
|
}
|
|
6478
|
-
function
|
|
6479
|
-
|
|
6480
|
-
try {
|
|
6481
|
-
raw = JSON.parse(stripBom(readFileSync5(filePath, "utf8")));
|
|
6482
|
-
} catch (error) {
|
|
6483
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
6484
|
-
throw new Error(`Cejel: could not parse ingest file as JSON: ${filePath} (${message})`);
|
|
6485
|
-
}
|
|
6486
|
-
let signals;
|
|
6487
|
-
if (looksLikeSarif(raw)) signals = parseSarifJson(raw);
|
|
6488
|
-
else if (looksLikeScorecard(raw)) signals = parseScorecardJson(raw);
|
|
6489
|
-
else if (isGenericSignalDocument(raw)) signals = parseGenericJson(raw);
|
|
6490
|
-
if (!signals) {
|
|
6491
|
-
throw new Error(
|
|
6492
|
-
`Cejel: unrecognized ingest file format: ${filePath} \u2014 expected SARIF (a "runs" array), OpenSSF Scorecard JSON (a "checks" array), or the generic Cejel external-signal shape (a "tool" string + "signals" array). See the cejel README "Aggregate your scanners".`
|
|
6493
|
-
);
|
|
6494
|
-
}
|
|
6495
|
-
const rawCount = countRawEntries(raw);
|
|
6496
|
-
const mappedCount = signals.reduce((sum, signal) => sum + signal.findings.length, 0);
|
|
6497
|
-
if (rawCount > 0 && mappedCount === 0) {
|
|
6498
|
-
process.stderr.write(
|
|
6499
|
-
`Cejel: ${rawCount} findings from ${rawToolName(raw)} (${filePath}), 0 mapped to trust criteria
|
|
6500
|
-
`
|
|
6501
|
-
);
|
|
6502
|
-
}
|
|
6503
|
-
return signals.map((signal) => ({
|
|
6504
|
-
...signal,
|
|
6505
|
-
findings: signal.findings.map(clampFinding)
|
|
6506
|
-
}));
|
|
4807
|
+
function escapeXml(value) {
|
|
4808
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
6507
4809
|
}
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
4810
|
+
|
|
4811
|
+
// src/witan/attestation.ts
|
|
4812
|
+
import { createHash } from "crypto";
|
|
4813
|
+
var ATTESTATION_LIMITATIONS = [
|
|
4814
|
+
"Cejel measures observable repository signals; it is not a security or compliance guarantee.",
|
|
4815
|
+
"This statement is self-generated and unsigned until an external signer binds their identity to it."
|
|
4816
|
+
];
|
|
4817
|
+
function serializeWitanReport(report) {
|
|
4818
|
+
return JSON.stringify(report, null, 2);
|
|
4819
|
+
}
|
|
4820
|
+
function hashWitanReport(report) {
|
|
4821
|
+
return createHash("sha256").update(serializeWitanReport(report), "utf8").digest("hex");
|
|
4822
|
+
}
|
|
4823
|
+
function createWitanAttestation(report, options) {
|
|
4824
|
+
const reportSha256 = hashWitanReport(report);
|
|
4825
|
+
const outcome = report.verdict === "insufficient_source" ? {
|
|
4826
|
+
status: "abstained",
|
|
4827
|
+
reason: report.insufficientSourceReason
|
|
4828
|
+
} : {
|
|
4829
|
+
status: "scored",
|
|
4830
|
+
overallScore: report.overallScore,
|
|
4831
|
+
codeTrustScore: report.codeTrustScore,
|
|
4832
|
+
processTrustScore: report.processTrustScore
|
|
4833
|
+
};
|
|
4834
|
+
return WitanAttestationStatementSchema.parse({
|
|
4835
|
+
_type: WITAN_ATTESTATION_STATEMENT_TYPE,
|
|
4836
|
+
subject: [
|
|
4837
|
+
{
|
|
4838
|
+
name: `${report.productSlug}/report.json`,
|
|
4839
|
+
digest: { sha256: reportSha256 }
|
|
4840
|
+
}
|
|
4841
|
+
],
|
|
4842
|
+
predicateType: WITAN_ATTESTATION_PREDICATE_TYPE,
|
|
4843
|
+
predicate: {
|
|
4844
|
+
tool: { name: "cejel", version: options.toolVersion },
|
|
4845
|
+
generatedAt: report.generatedAt,
|
|
4846
|
+
rubricVersion: report.rubricVersion,
|
|
4847
|
+
repository: {
|
|
4848
|
+
productSlug: report.productSlug,
|
|
4849
|
+
...report.repo.url ? { url: report.repo.url } : {},
|
|
4850
|
+
...report.repo.headSha ? { headSha: report.repo.headSha } : {}
|
|
4851
|
+
},
|
|
4852
|
+
report: {
|
|
4853
|
+
artifact: "report.json",
|
|
4854
|
+
sha256: reportSha256
|
|
4855
|
+
},
|
|
4856
|
+
outcome,
|
|
4857
|
+
assurance: {
|
|
4858
|
+
status: "unsigned",
|
|
4859
|
+
issuer: "self-generated",
|
|
4860
|
+
signingHint: "Sign this in-toto statement with your existing provenance system; verify the report digest before relying on it."
|
|
4861
|
+
},
|
|
4862
|
+
limitations: [...ATTESTATION_LIMITATIONS]
|
|
4863
|
+
}
|
|
4864
|
+
});
|
|
6522
4865
|
}
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
4866
|
+
|
|
4867
|
+
// src/witan/repo-signals.ts
|
|
4868
|
+
import { execFileSync } from "child_process";
|
|
4869
|
+
import { createHash as createHash2 } from "crypto";
|
|
4870
|
+
import { readFileSync, readdirSync, realpathSync, statSync } from "fs";
|
|
4871
|
+
import { basename, join, relative, resolve, sep } from "path";
|
|
4872
|
+
|
|
4873
|
+
// src/witan/json-safe.ts
|
|
4874
|
+
function stripBom(text) {
|
|
4875
|
+
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
6532
4876
|
}
|
|
6533
4877
|
|
|
6534
|
-
//
|
|
6535
|
-
import { execFileSync } from "child_process";
|
|
6536
|
-
import { createHash } from "crypto";
|
|
6537
|
-
import { readFileSync as readFileSync6, readdirSync as readdirSync3, realpathSync, statSync as statSync2 } from "fs";
|
|
6538
|
-
import { basename, join as join3, relative, resolve, sep } from "path";
|
|
4878
|
+
// src/witan/repo-signals.ts
|
|
6539
4879
|
function buildWitanInputFromRepo(options) {
|
|
6540
4880
|
assertRepoPathExists(options.repoPath);
|
|
6541
4881
|
const generatedAt = options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -6702,7 +5042,7 @@ function isLikelyMonorepo(repoFiles) {
|
|
|
6702
5042
|
function assertRepoPathExists(repoPath) {
|
|
6703
5043
|
let stats;
|
|
6704
5044
|
try {
|
|
6705
|
-
stats =
|
|
5045
|
+
stats = statSync(repoPath);
|
|
6706
5046
|
} catch {
|
|
6707
5047
|
throw new Error(`Cejel: path not found: ${repoPath}`);
|
|
6708
5048
|
}
|
|
@@ -6770,7 +5110,7 @@ function collectA1TestIntegrityEvidence(repoPath, repoFiles) {
|
|
|
6770
5110
|
const runnerFiles = repoFiles.filter(isTestRunnerConfig).slice(0, 6);
|
|
6771
5111
|
const coverageFiles = repoFiles.filter(isCoverageConfig).slice(0, 4);
|
|
6772
5112
|
const packageJson = findRootPackageJson(repoFiles);
|
|
6773
|
-
const packageScripts = packageJson ? readPackageScripts(
|
|
5113
|
+
const packageScripts = packageJson ? readPackageScripts(join(repoPath, packageJson)) : /* @__PURE__ */ new Map();
|
|
6774
5114
|
const coveragePercent = readCoveragePercent(repoPath, coverageFiles);
|
|
6775
5115
|
const ciWorkflows = repoFiles.filter(isCiWorkflow);
|
|
6776
5116
|
const ciTestWorkflow = ciWorkflows.find(
|
|
@@ -7231,7 +5571,7 @@ function collectA3ProdReadinessEvidence(repoPath, repoFiles) {
|
|
|
7231
5571
|
const evidence = [];
|
|
7232
5572
|
const findings = [];
|
|
7233
5573
|
const packageJson = findRootPackageJson(repoFiles);
|
|
7234
|
-
const scripts = packageJson ? readPackageScripts(
|
|
5574
|
+
const scripts = packageJson ? readPackageScripts(join(repoPath, packageJson)) : /* @__PURE__ */ new Map();
|
|
7235
5575
|
const workflows = repoFiles.filter(isCiWorkflow);
|
|
7236
5576
|
const workflow = workflows[0];
|
|
7237
5577
|
const deployConfigs = repoFiles.filter(isDeployConfig);
|
|
@@ -7665,7 +6005,7 @@ function collectB2PrTraceEvidence(repoPath, repoFiles) {
|
|
|
7665
6005
|
function collectB3CiDisciplineEvidence(repoPath, repoFiles, mono) {
|
|
7666
6006
|
const evidence = [];
|
|
7667
6007
|
const packageJson = findRootPackageJson(repoFiles);
|
|
7668
|
-
const scripts = packageJson ? readPackageScripts(
|
|
6008
|
+
const scripts = packageJson ? readPackageScripts(join(repoPath, packageJson)) : /* @__PURE__ */ new Map();
|
|
7669
6009
|
const workflows = repoFiles.filter(isCiWorkflow);
|
|
7670
6010
|
const workflow = workflows[0];
|
|
7671
6011
|
const rootWorkflows = mono ? mono.sharedFiles.filter(isCiWorkflow) : [];
|
|
@@ -7986,16 +6326,16 @@ function lineHasInsecureSecretCompare(line) {
|
|
|
7986
6326
|
return !NUMERIC_SHAPED_OPERAND_PATTERN.test(operand.trim());
|
|
7987
6327
|
}
|
|
7988
6328
|
function findInsecureSecretCompareLine(repoPath, file) {
|
|
7989
|
-
const fullPath =
|
|
6329
|
+
const fullPath = join(repoPath, file);
|
|
7990
6330
|
if (!isRegularFile(fullPath)) return null;
|
|
7991
|
-
const lines =
|
|
6331
|
+
const lines = readFileSync(fullPath, "utf8").split("\n");
|
|
7992
6332
|
const index = lines.findIndex((line) => lineHasInsecureSecretCompare(line));
|
|
7993
6333
|
return index === -1 ? null : index + 1;
|
|
7994
6334
|
}
|
|
7995
6335
|
function findFirstMatchingLine(repoPath, file, pattern) {
|
|
7996
|
-
const fullPath =
|
|
6336
|
+
const fullPath = join(repoPath, file);
|
|
7997
6337
|
if (!isRegularFile(fullPath)) return null;
|
|
7998
|
-
const lines =
|
|
6338
|
+
const lines = readFileSync(fullPath, "utf8").split("\n");
|
|
7999
6339
|
const index = lines.findIndex((line) => pattern.test(line));
|
|
8000
6340
|
return index === -1 ? null : index + 1;
|
|
8001
6341
|
}
|
|
@@ -8110,13 +6450,13 @@ function listGitTrackedFiles(repoPath) {
|
|
|
8110
6450
|
function visitRepoDir(repoPath, dirPath, files) {
|
|
8111
6451
|
let entries;
|
|
8112
6452
|
try {
|
|
8113
|
-
entries =
|
|
6453
|
+
entries = readdirSync(dirPath, { withFileTypes: true });
|
|
8114
6454
|
} catch {
|
|
8115
6455
|
return;
|
|
8116
6456
|
}
|
|
8117
6457
|
for (const entry of entries) {
|
|
8118
6458
|
if (shouldSkipDir(entry.name)) continue;
|
|
8119
|
-
const fullPath =
|
|
6459
|
+
const fullPath = join(dirPath, entry.name);
|
|
8120
6460
|
if (entry.isDirectory()) {
|
|
8121
6461
|
visitRepoDir(repoPath, fullPath, files);
|
|
8122
6462
|
continue;
|
|
@@ -8124,7 +6464,7 @@ function visitRepoDir(repoPath, dirPath, files) {
|
|
|
8124
6464
|
if (!entry.isFile()) continue;
|
|
8125
6465
|
let size;
|
|
8126
6466
|
try {
|
|
8127
|
-
size =
|
|
6467
|
+
size = statSync(fullPath).size;
|
|
8128
6468
|
} catch {
|
|
8129
6469
|
continue;
|
|
8130
6470
|
}
|
|
@@ -8155,9 +6495,9 @@ function isHardExcludedPath(path) {
|
|
|
8155
6495
|
function collectContentBasedCppTestFiles(repoPath, repoFiles) {
|
|
8156
6496
|
const candidates = repoFiles.filter((file) => /\.(cpp|cc|cxx)$/.test(file) && !isTestFile(file)).slice(0, CPP_CONTENT_SCAN_LIMIT);
|
|
8157
6497
|
return candidates.filter((file) => {
|
|
8158
|
-
const fullPath =
|
|
6498
|
+
const fullPath = join(repoPath, file);
|
|
8159
6499
|
if (!isRegularFile(fullPath)) return false;
|
|
8160
|
-
const contents =
|
|
6500
|
+
const contents = readFileSync(fullPath, "utf8");
|
|
8161
6501
|
return CPP_TEST_FRAMEWORK_PATTERN.test(contents) || CPP_TEST_MACRO_PATTERN.test(contents);
|
|
8162
6502
|
});
|
|
8163
6503
|
}
|
|
@@ -8175,9 +6515,9 @@ function measureNonHollowTestShare(repoPath, files) {
|
|
|
8175
6515
|
let nonHollowCount = 0;
|
|
8176
6516
|
let ratedCount = 0;
|
|
8177
6517
|
for (const file of files) {
|
|
8178
|
-
const fullPath =
|
|
6518
|
+
const fullPath = join(repoPath, file);
|
|
8179
6519
|
if (!isRegularFile(fullPath)) continue;
|
|
8180
|
-
const contents =
|
|
6520
|
+
const contents = readFileSync(fullPath, "utf8");
|
|
8181
6521
|
const nonHollow = (JS_TEST_ASSERTION_PATTERN.test(contents) || CPP_TEST_ASSERTION_PATTERN.test(contents) || MULTI_ECOSYSTEM_TEST_ASSERTION_PATTERN.test(contents)) && !SUITE_LEVEL_SKIP_PATTERN.test(contents);
|
|
8182
6522
|
if (nonHollow) {
|
|
8183
6523
|
nonHollowCount += 1;
|
|
@@ -8196,17 +6536,17 @@ function countPatternMatches(repoPath, files, pattern) {
|
|
|
8196
6536
|
const matcher = new RegExp(pattern.source, flags);
|
|
8197
6537
|
let count = 0;
|
|
8198
6538
|
for (const file of files) {
|
|
8199
|
-
const fullPath =
|
|
6539
|
+
const fullPath = join(repoPath, file);
|
|
8200
6540
|
if (!isRegularFile(fullPath)) continue;
|
|
8201
|
-
count += [...
|
|
6541
|
+
count += [...readFileSync(fullPath, "utf8").matchAll(matcher)].length;
|
|
8202
6542
|
}
|
|
8203
6543
|
return count;
|
|
8204
6544
|
}
|
|
8205
6545
|
function readCoveragePercent(repoPath, files) {
|
|
8206
6546
|
for (const file of files) {
|
|
8207
|
-
const fullPath =
|
|
6547
|
+
const fullPath = join(repoPath, file);
|
|
8208
6548
|
if (!isRegularFile(fullPath)) continue;
|
|
8209
|
-
const contents =
|
|
6549
|
+
const contents = readFileSync(fullPath, "utf8");
|
|
8210
6550
|
const summaryPercent = parseCoverageSummaryPercent(contents);
|
|
8211
6551
|
if (summaryPercent !== null) return summaryPercent;
|
|
8212
6552
|
const thresholdPercent = parseCoverageThresholdPercent(contents);
|
|
@@ -8250,7 +6590,7 @@ function pickPrimaryDependencyManifest(repoPath, manifests) {
|
|
|
8250
6590
|
function readDependencySpecs(repoPath, manifests) {
|
|
8251
6591
|
const specs = [];
|
|
8252
6592
|
for (const manifest of manifests) {
|
|
8253
|
-
const fullPath =
|
|
6593
|
+
const fullPath = join(repoPath, manifest);
|
|
8254
6594
|
if (!isRegularFile(fullPath)) continue;
|
|
8255
6595
|
if (manifest.endsWith("package.json")) {
|
|
8256
6596
|
specs.push(...readPackageJsonDependencySpecs(fullPath));
|
|
@@ -8296,7 +6636,7 @@ function readDependencySpecs(repoPath, manifests) {
|
|
|
8296
6636
|
}
|
|
8297
6637
|
function readGoModDependencySpecs(path) {
|
|
8298
6638
|
const specs = [];
|
|
8299
|
-
const contents =
|
|
6639
|
+
const contents = readFileSync(path, "utf8");
|
|
8300
6640
|
const blockPattern = /require\s*\(([^)]+)\)/gs;
|
|
8301
6641
|
const singlePattern = /^require\s+(\S+)\s+(\S+)/gm;
|
|
8302
6642
|
for (const blockMatch of contents.matchAll(blockPattern)) {
|
|
@@ -8317,7 +6657,7 @@ function readGoModDependencySpecs(path) {
|
|
|
8317
6657
|
}
|
|
8318
6658
|
function readCargoTomlDependencySpecs(path) {
|
|
8319
6659
|
const specs = [];
|
|
8320
|
-
const contents =
|
|
6660
|
+
const contents = readFileSync(path, "utf8");
|
|
8321
6661
|
const depSectionPattern = /^\[(?:dependencies|dev-dependencies|build-dependencies)\]([\s\S]*?)(?=^\[|(?![\s\S]))/gm;
|
|
8322
6662
|
for (const sectionMatch of contents.matchAll(depSectionPattern)) {
|
|
8323
6663
|
const section = sectionMatch[1] ?? "";
|
|
@@ -8339,7 +6679,7 @@ function readCargoTomlDependencySpecs(path) {
|
|
|
8339
6679
|
}
|
|
8340
6680
|
function readPyprojectDependencySpecs(path) {
|
|
8341
6681
|
const specs = [];
|
|
8342
|
-
const contents =
|
|
6682
|
+
const contents = readFileSync(path, "utf8");
|
|
8343
6683
|
const poetrySectionPattern = /^\[tool\.poetry\.dependencies\]([\s\S]*?)(?=^\[|(?![\s\S]))/gm;
|
|
8344
6684
|
for (const sectionMatch of contents.matchAll(poetrySectionPattern)) {
|
|
8345
6685
|
const section = sectionMatch[1] ?? "";
|
|
@@ -8373,7 +6713,7 @@ function readPyprojectDependencySpecs(path) {
|
|
|
8373
6713
|
}
|
|
8374
6714
|
function readPipfileDependencySpecs(path) {
|
|
8375
6715
|
const specs = [];
|
|
8376
|
-
const contents =
|
|
6716
|
+
const contents = readFileSync(path, "utf8");
|
|
8377
6717
|
const sectionPattern = /^\[(?:packages|dev-packages)\]([\s\S]*?)(?=^\[|$(?![\s\S]))/gm;
|
|
8378
6718
|
for (const sectionMatch of contents.matchAll(sectionPattern)) {
|
|
8379
6719
|
for (const line of (sectionMatch[1] ?? "").split("\n")) {
|
|
@@ -8386,7 +6726,7 @@ function readPipfileDependencySpecs(path) {
|
|
|
8386
6726
|
return specs;
|
|
8387
6727
|
}
|
|
8388
6728
|
function readVcpkgJsonDependencySpecs(path) {
|
|
8389
|
-
const parsed = parseJsonObject(
|
|
6729
|
+
const parsed = parseJsonObject(readFileSync(path, "utf8"));
|
|
8390
6730
|
if (!parsed) return [];
|
|
8391
6731
|
const rawDeps = Array.isArray(parsed.dependencies) ? parsed.dependencies : [];
|
|
8392
6732
|
const specs = [];
|
|
@@ -8402,7 +6742,7 @@ function readVcpkgJsonDependencySpecs(path) {
|
|
|
8402
6742
|
}
|
|
8403
6743
|
function readConanfileTxtDependencySpecs(path) {
|
|
8404
6744
|
const specs = [];
|
|
8405
|
-
const contents =
|
|
6745
|
+
const contents = readFileSync(path, "utf8");
|
|
8406
6746
|
const requiresMatch = /^\[requires\]([\s\S]*?)(?=^\[|$(?![\s\S]))/m.exec(contents);
|
|
8407
6747
|
if (!requiresMatch) return specs;
|
|
8408
6748
|
for (const line of (requiresMatch[1] ?? "").split("\n")) {
|
|
@@ -8415,7 +6755,7 @@ function readConanfileTxtDependencySpecs(path) {
|
|
|
8415
6755
|
}
|
|
8416
6756
|
function readConanfilePyDependencySpecs(path) {
|
|
8417
6757
|
const specs = [];
|
|
8418
|
-
const contents =
|
|
6758
|
+
const contents = readFileSync(path, "utf8");
|
|
8419
6759
|
for (const match of contents.matchAll(/self\.requires\s*\(\s*["']([\w.\-]+)\/([\w.\-]+)["']/g)) {
|
|
8420
6760
|
specs.push({ name: match[1] ?? "", version: match[2] ?? "" });
|
|
8421
6761
|
}
|
|
@@ -8429,7 +6769,7 @@ function readConanfilePyDependencySpecs(path) {
|
|
|
8429
6769
|
}
|
|
8430
6770
|
function readCMakeDependencySpecs(path) {
|
|
8431
6771
|
const specs = [];
|
|
8432
|
-
const contents =
|
|
6772
|
+
const contents = readFileSync(path, "utf8");
|
|
8433
6773
|
for (const match of contents.matchAll(/find_package\s*\(\s*([\w]+)(?:\s+([\d.]+))?/gi)) {
|
|
8434
6774
|
const name = match[1];
|
|
8435
6775
|
if (!name) continue;
|
|
@@ -8444,7 +6784,7 @@ function readCMakeDependencySpecs(path) {
|
|
|
8444
6784
|
return specs;
|
|
8445
6785
|
}
|
|
8446
6786
|
function readPackageJsonDependencySpecs(packageJsonPath) {
|
|
8447
|
-
const parsed = parseJsonObject(
|
|
6787
|
+
const parsed = parseJsonObject(readFileSync(packageJsonPath, "utf8"));
|
|
8448
6788
|
if (!parsed) return [];
|
|
8449
6789
|
const optionalPeerNames = /* @__PURE__ */ new Set();
|
|
8450
6790
|
const peerDependenciesMeta = parsed.peerDependenciesMeta;
|
|
@@ -8471,7 +6811,7 @@ function readPackageJsonDependencySpecs(packageJsonPath) {
|
|
|
8471
6811
|
return specs;
|
|
8472
6812
|
}
|
|
8473
6813
|
function readRequirementsDependencySpecs(path) {
|
|
8474
|
-
return
|
|
6814
|
+
return readFileSync(path, "utf8").split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map((line) => {
|
|
8475
6815
|
const [name = line, version = ""] = line.split(/[<>=~!]=?/, 2);
|
|
8476
6816
|
return { name: name.trim(), version: line.includes("==") ? version.trim() : line };
|
|
8477
6817
|
});
|
|
@@ -8487,9 +6827,9 @@ function isPinnedDependencyVersion(version) {
|
|
|
8487
6827
|
return /^\d+\.\d+(?:\.\d+)?(?:[-+][0-9A-Za-z.-]+)?$/.test(trimmed);
|
|
8488
6828
|
}
|
|
8489
6829
|
function workflowTargetsDefaultBranch(repoPath, file) {
|
|
8490
|
-
const fullPath =
|
|
6830
|
+
const fullPath = join(repoPath, file);
|
|
8491
6831
|
if (!isRegularFile(fullPath)) return false;
|
|
8492
|
-
const contents =
|
|
6832
|
+
const contents = readFileSync(fullPath, "utf8").toLowerCase();
|
|
8493
6833
|
return /\bpull_request\b/.test(contents) || /\bbranches:\s*\[[^\]]*\b(main|master)\b[^\]]*\]/.test(contents) || /\bbranches:\s*\n\s*-\s*(main|master)\b/.test(contents);
|
|
8494
6834
|
}
|
|
8495
6835
|
function isPrMergeCommit(commit) {
|
|
@@ -8571,384 +6911,767 @@ function isLockfile(file) {
|
|
|
8571
6911
|
function isDependencyUpdateConfig(file) {
|
|
8572
6912
|
return /(^|\/)(renovate\.json|renovate\.json5|\.renovaterc\.json|dependabot\.ya?ml)$/.test(file) || /^\.github\/dependabot\.ya?ml$/.test(file);
|
|
8573
6913
|
}
|
|
8574
|
-
function packageJsonHasAuditScript(repoPath, manifest) {
|
|
8575
|
-
if (!manifest.endsWith("package.json")) return false;
|
|
8576
|
-
const scripts = readPackageScripts(
|
|
8577
|
-
return [...scripts.values()].some(
|
|
8578
|
-
(script) => /\b(audit|npm audit|pnpm audit|yarn audit)\b/i.test(script)
|
|
8579
|
-
);
|
|
6914
|
+
function packageJsonHasAuditScript(repoPath, manifest) {
|
|
6915
|
+
if (!manifest.endsWith("package.json")) return false;
|
|
6916
|
+
const scripts = readPackageScripts(join(repoPath, manifest));
|
|
6917
|
+
return [...scripts.values()].some(
|
|
6918
|
+
(script) => /\b(audit|npm audit|pnpm audit|yarn audit)\b/i.test(script)
|
|
6919
|
+
);
|
|
6920
|
+
}
|
|
6921
|
+
function packageJsonHasHeavyTestDependency(repoPath, manifest) {
|
|
6922
|
+
const fullPath = join(repoPath, manifest);
|
|
6923
|
+
if (!isRegularFile(fullPath)) return false;
|
|
6924
|
+
const parsed = parseJsonObject(readFileSync(fullPath, "utf8"));
|
|
6925
|
+
if (!parsed) return false;
|
|
6926
|
+
const names = [
|
|
6927
|
+
...Object.keys(isRecord(parsed.dependencies) ? parsed.dependencies : {}),
|
|
6928
|
+
...Object.keys(isRecord(parsed.devDependencies) ? parsed.devDependencies : {})
|
|
6929
|
+
];
|
|
6930
|
+
return names.some((name) => HEAVY_TEST_DEPENDENCY_NAME_PATTERN.test(name));
|
|
6931
|
+
}
|
|
6932
|
+
function isImplementationFile(file) {
|
|
6933
|
+
return /(^|\/)(src|app|lib|packages|cmd|include|source|Sources)\//.test(file) && /\.(ts|tsx|js|jsx|py|go|rs|java|rb|cpp|cc|cxx|c|h|hpp|kt|swift|php)$/.test(file);
|
|
6934
|
+
}
|
|
6935
|
+
function isAuditFile(file) {
|
|
6936
|
+
return (
|
|
6937
|
+
// goal_cejel_calibration_fix_with_strict_gate_2026-07-06: mature OSS repos document the
|
|
6938
|
+
// same audit-trail practice under different filenames/extensions than Alfred's own
|
|
6939
|
+
// conventions (Flask ships CHANGES.rst, not CHANGELOG.md) — recognize the common OSS
|
|
6940
|
+
// release-notes/security-policy/provenance equivalents so real audit-trail artifacts are
|
|
6941
|
+
// credited instead of silently missing the pattern.
|
|
6942
|
+
/(^|\/)(CHANGELOG|CHANGES|HISTORY|NEWS|RELEASE_NOTES|RELEASES|SECURITY|AUDIT|STATUS)\.(md|rst|txt)$/i.test(
|
|
6943
|
+
file
|
|
6944
|
+
) || /(^|\/)docs\/.*(audit|runbook|incident|changelog|security).*\.(md|rst)$/i.test(file) || // Provenance/signed-release tooling config is itself audit-trail evidence (a repo that
|
|
6945
|
+
// wires SLSA/cosign attestation or CITATION.cff is documenting release provenance).
|
|
6946
|
+
/(^|\/)CITATION\.cff$/i.test(file)
|
|
6947
|
+
);
|
|
6948
|
+
}
|
|
6949
|
+
function isSecurityPolicyOnlyAuditFile(file) {
|
|
6950
|
+
return /(^|\/)SECURITY\.(md|rst|txt)$/i.test(file) || /(^|\/)docs\/.*security.*\.(md|rst)$/i.test(file);
|
|
6951
|
+
}
|
|
6952
|
+
function isFreshnessRatableAuditFile(file) {
|
|
6953
|
+
return isAuditFile(file) && !isSecurityPolicyOnlyAuditFile(file);
|
|
6954
|
+
}
|
|
6955
|
+
function isIgnoredScanFile(file) {
|
|
6956
|
+
return /(^|\/)(package-lock\.json|pnpm-lock\.yaml|yarn\.lock|README\.md|CHANGELOG\.md)$/.test(file) || isEnvTemplatePath(file);
|
|
6957
|
+
}
|
|
6958
|
+
function findRootPackageJson(repoFiles) {
|
|
6959
|
+
return repoFiles.includes("package.json") ? "package.json" : null;
|
|
6960
|
+
}
|
|
6961
|
+
function isRegularFile(path) {
|
|
6962
|
+
try {
|
|
6963
|
+
return statSync(path).isFile();
|
|
6964
|
+
} catch {
|
|
6965
|
+
return false;
|
|
6966
|
+
}
|
|
6967
|
+
}
|
|
6968
|
+
function fileContains(repoPath, file, pattern) {
|
|
6969
|
+
const fullPath = join(repoPath, file);
|
|
6970
|
+
if (!isRegularFile(fullPath)) return false;
|
|
6971
|
+
return pattern.test(readFileSync(fullPath, "utf8"));
|
|
6972
|
+
}
|
|
6973
|
+
function fileContainsCommittedSecret(repoPath, file) {
|
|
6974
|
+
const fullPath = join(repoPath, file);
|
|
6975
|
+
if (!isRegularFile(fullPath)) return false;
|
|
6976
|
+
return containsRealSecret(readFileSync(fullPath, "utf8"));
|
|
6977
|
+
}
|
|
6978
|
+
function containsRealSecret(contents) {
|
|
6979
|
+
SECRET_ASSIGNMENT_PATTERN.lastIndex = 0;
|
|
6980
|
+
for (const match of contents.matchAll(SECRET_ASSIGNMENT_PATTERN)) {
|
|
6981
|
+
const rawValue = match[1];
|
|
6982
|
+
if (!rawValue) continue;
|
|
6983
|
+
const value = rawValue.replace(/[,;)]$/, "");
|
|
6984
|
+
if (isPlaceholderSecretValue(value)) continue;
|
|
6985
|
+
if (looksLikeSecretValue(value)) return true;
|
|
6986
|
+
}
|
|
6987
|
+
return false;
|
|
6988
|
+
}
|
|
6989
|
+
function collectHistorySecretEvidence(repoPath) {
|
|
6990
|
+
const historyEntries = readCredentialHistoryEntries(repoPath);
|
|
6991
|
+
let scannedFiles = 0;
|
|
6992
|
+
let envPathEvidence = null;
|
|
6993
|
+
for (const entry of historyEntries) {
|
|
6994
|
+
if (scannedFiles >= HISTORY_SECRET_SCAN_CREDENTIAL_BLOB_LIMIT) {
|
|
6995
|
+
return { evidence: null, envPathEvidence, truncated: true };
|
|
6996
|
+
}
|
|
6997
|
+
scannedFiles += 1;
|
|
6998
|
+
const contents = readGitBlob(repoPath, entry.commit, entry.path);
|
|
6999
|
+
if (!contents) continue;
|
|
7000
|
+
if (containsRealSecret(contents)) {
|
|
7001
|
+
return {
|
|
7002
|
+
evidence: {
|
|
7003
|
+
kind: "secret_scan",
|
|
7004
|
+
label: "Committed secret in recent git history",
|
|
7005
|
+
path: entry.path,
|
|
7006
|
+
contentHash: entry.commit
|
|
7007
|
+
},
|
|
7008
|
+
envPathEvidence,
|
|
7009
|
+
truncated: false
|
|
7010
|
+
};
|
|
7011
|
+
}
|
|
7012
|
+
if (!envPathEvidence && isEnvHistoryPath(entry.path)) {
|
|
7013
|
+
envPathEvidence = {
|
|
7014
|
+
kind: "secret_scan",
|
|
7015
|
+
label: ".env file (not a template) tracked in git history; no confirmed secret value found",
|
|
7016
|
+
path: entry.path,
|
|
7017
|
+
contentHash: entry.commit
|
|
7018
|
+
};
|
|
7019
|
+
}
|
|
7020
|
+
}
|
|
7021
|
+
return { evidence: null, envPathEvidence, truncated: false };
|
|
7022
|
+
}
|
|
7023
|
+
function readCredentialHistoryEntries(repoPath) {
|
|
7024
|
+
const entries = [];
|
|
7025
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7026
|
+
const appendEntry = (entry) => {
|
|
7027
|
+
const key = `${entry.commit}:${entry.path}`;
|
|
7028
|
+
if (seen.has(key)) return;
|
|
7029
|
+
seen.add(key);
|
|
7030
|
+
entries.push(entry);
|
|
7031
|
+
};
|
|
7032
|
+
try {
|
|
7033
|
+
const commits = execFileSync("git", ["rev-list", "--all"], {
|
|
7034
|
+
cwd: repoPath,
|
|
7035
|
+
encoding: "utf8",
|
|
7036
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7037
|
+
});
|
|
7038
|
+
const output = execFileSync(
|
|
7039
|
+
"git",
|
|
7040
|
+
[
|
|
7041
|
+
"diff-tree",
|
|
7042
|
+
"--stdin",
|
|
7043
|
+
"--root",
|
|
7044
|
+
"--name-only",
|
|
7045
|
+
"-r",
|
|
7046
|
+
"--diff-filter=AM",
|
|
7047
|
+
"--pretty=format:commit:%H"
|
|
7048
|
+
],
|
|
7049
|
+
{
|
|
7050
|
+
cwd: repoPath,
|
|
7051
|
+
encoding: "utf8",
|
|
7052
|
+
input: commits,
|
|
7053
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
7054
|
+
}
|
|
7055
|
+
);
|
|
7056
|
+
let currentCommit = null;
|
|
7057
|
+
for (const line of output.split("\n")) {
|
|
7058
|
+
if (line.startsWith("commit:")) {
|
|
7059
|
+
currentCommit = line.slice("commit:".length);
|
|
7060
|
+
continue;
|
|
7061
|
+
}
|
|
7062
|
+
const path = line.trim();
|
|
7063
|
+
if (!currentCommit || !path) continue;
|
|
7064
|
+
if (!isCredentialHistoryPath(path)) continue;
|
|
7065
|
+
appendEntry({ commit: currentCommit, path });
|
|
7066
|
+
}
|
|
7067
|
+
} catch {
|
|
7068
|
+
}
|
|
7069
|
+
for (const entry of readDeletedCredentialHistoryEntries(repoPath)) {
|
|
7070
|
+
appendEntry(entry);
|
|
7071
|
+
}
|
|
7072
|
+
return entries;
|
|
7073
|
+
}
|
|
7074
|
+
function readDeletedCredentialHistoryEntries(repoPath) {
|
|
7075
|
+
const deletedPaths = readDeletedCredentialHistoryPaths(repoPath);
|
|
7076
|
+
const entries = [];
|
|
7077
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7078
|
+
for (const path of deletedPaths) {
|
|
7079
|
+
for (const commit of readHistoryCommitsForPath(repoPath, path)) {
|
|
7080
|
+
const key = `${commit}:${path}`;
|
|
7081
|
+
if (seen.has(key)) continue;
|
|
7082
|
+
seen.add(key);
|
|
7083
|
+
entries.push({ commit, path });
|
|
7084
|
+
}
|
|
7085
|
+
}
|
|
7086
|
+
return entries;
|
|
7087
|
+
}
|
|
7088
|
+
function readDeletedCredentialHistoryPaths(repoPath) {
|
|
7089
|
+
try {
|
|
7090
|
+
const output = execFileSync(
|
|
7091
|
+
"git",
|
|
7092
|
+
["log", "--all", "--diff-filter=D", "--name-status", "--format=commit:%H"],
|
|
7093
|
+
{
|
|
7094
|
+
cwd: repoPath,
|
|
7095
|
+
encoding: "utf8",
|
|
7096
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7097
|
+
}
|
|
7098
|
+
);
|
|
7099
|
+
const paths = [];
|
|
7100
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7101
|
+
for (const line of output.split("\n")) {
|
|
7102
|
+
if (!line.startsWith("D ")) continue;
|
|
7103
|
+
const path = line.slice(2).trim();
|
|
7104
|
+
if (!path || seen.has(path)) continue;
|
|
7105
|
+
if (!isCredentialHistoryPath(path)) continue;
|
|
7106
|
+
seen.add(path);
|
|
7107
|
+
paths.push(path);
|
|
7108
|
+
}
|
|
7109
|
+
return paths;
|
|
7110
|
+
} catch {
|
|
7111
|
+
return [];
|
|
7112
|
+
}
|
|
7113
|
+
}
|
|
7114
|
+
function readHistoryCommitsForPath(repoPath, path) {
|
|
7115
|
+
try {
|
|
7116
|
+
const output = execFileSync(
|
|
7117
|
+
"git",
|
|
7118
|
+
["log", "--all", "--diff-filter=AM", "--format=%H", "--", path],
|
|
7119
|
+
{
|
|
7120
|
+
cwd: repoPath,
|
|
7121
|
+
encoding: "utf8",
|
|
7122
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7123
|
+
}
|
|
7124
|
+
);
|
|
7125
|
+
return output.split("\n").map((line) => line.trim()).filter((line) => /^[0-9a-f]{40}$/i.test(line));
|
|
7126
|
+
} catch {
|
|
7127
|
+
return [];
|
|
7128
|
+
}
|
|
7129
|
+
}
|
|
7130
|
+
function isCredentialHistoryPath(path) {
|
|
7131
|
+
if (isHardExcludedPath(path)) return false;
|
|
7132
|
+
const lowerPath = path.toLowerCase();
|
|
7133
|
+
const basename3 = lowerPath.split("/").at(-1) ?? lowerPath;
|
|
7134
|
+
if (/\.env(?:\.|$)/.test(basename3)) {
|
|
7135
|
+
return true;
|
|
7136
|
+
}
|
|
7137
|
+
return lowerPath.includes("secret") || lowerPath.includes("credential") || basename3.endsWith(".pem") || basename3.endsWith(".key") || basename3 === "id_rsa" || basename3.endsWith(".p12") || basename3.endsWith(".pfx");
|
|
7138
|
+
}
|
|
7139
|
+
function isEnvHistoryPath(path) {
|
|
7140
|
+
if (isEnvTemplatePath(path)) return false;
|
|
7141
|
+
const basename3 = path.toLowerCase().split("/").at(-1) ?? path.toLowerCase();
|
|
7142
|
+
return /\.env(?:\.|$)/.test(basename3);
|
|
7143
|
+
}
|
|
7144
|
+
function readGitBlob(repoPath, commit, path) {
|
|
7145
|
+
try {
|
|
7146
|
+
return execFileSync("git", ["show", `${commit}:${path}`], {
|
|
7147
|
+
cwd: repoPath,
|
|
7148
|
+
encoding: "utf8",
|
|
7149
|
+
maxBuffer: 512e3,
|
|
7150
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7151
|
+
});
|
|
7152
|
+
} catch {
|
|
7153
|
+
return null;
|
|
7154
|
+
}
|
|
7155
|
+
}
|
|
7156
|
+
var ALL_CAPS_SNAKE_PLACEHOLDER_PATTERN = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/;
|
|
7157
|
+
function isPlaceholderSecretValue(value) {
|
|
7158
|
+
const normalized = value.trim().toLowerCase();
|
|
7159
|
+
return PLACEHOLDER_SECRET_PATTERN.test(normalized) || normalized.includes("your-") || normalized.includes("example") || ALL_CAPS_SNAKE_PLACEHOLDER_PATTERN.test(value.trim()) || isSyntheticFixtureSecretValue(normalized) || isFillerRunSecretValue(normalized);
|
|
7160
|
+
}
|
|
7161
|
+
function isFillerRunSecretValue(value) {
|
|
7162
|
+
const candidates = [value];
|
|
7163
|
+
const sepIdx = Math.max(value.lastIndexOf("_"), value.lastIndexOf("-"));
|
|
7164
|
+
if (sepIdx > 0 && sepIdx < value.length - 1) {
|
|
7165
|
+
candidates.push(value.slice(sepIdx + 1));
|
|
7166
|
+
}
|
|
7167
|
+
for (const body of candidates) {
|
|
7168
|
+
if (body.length < 8) continue;
|
|
7169
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7170
|
+
for (const ch of body) counts.set(ch, (counts.get(ch) ?? 0) + 1);
|
|
7171
|
+
const distinct = counts.size;
|
|
7172
|
+
const maxRun = Math.max(...counts.values());
|
|
7173
|
+
if (distinct <= 2 && maxRun / body.length >= 0.8) return true;
|
|
7174
|
+
}
|
|
7175
|
+
return false;
|
|
7176
|
+
}
|
|
7177
|
+
function isSyntheticFixtureSecretValue(value) {
|
|
7178
|
+
return value.includes("abcdefghijklmnopqrstuvwxyz") || value.includes("0123456789abcdefghijklmnopqrstuvwxyz") || value.includes("abcdefghijklmnopqrstuvwxyz0123456789") || value.includes("abcdefghijklmnopqrst");
|
|
8580
7179
|
}
|
|
8581
|
-
function
|
|
8582
|
-
|
|
7180
|
+
function hasSuspiciousDependencies(repoPath, manifest) {
|
|
7181
|
+
if (!manifest.endsWith("package.json")) return false;
|
|
7182
|
+
const fullPath = join(repoPath, manifest);
|
|
8583
7183
|
if (!isRegularFile(fullPath)) return false;
|
|
8584
|
-
const parsed = parseJsonObject(
|
|
7184
|
+
const parsed = parseJsonObject(readFileSync(fullPath, "utf8"));
|
|
8585
7185
|
if (!parsed) return false;
|
|
8586
|
-
const
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
7186
|
+
const dependencies = isRecord(parsed.dependencies) ? parsed.dependencies : {};
|
|
7187
|
+
const devDependencies = isRecord(parsed.devDependencies) ? parsed.devDependencies : {};
|
|
7188
|
+
const names = [...Object.keys(dependencies), ...Object.keys(devDependencies)];
|
|
7189
|
+
return names.some(
|
|
7190
|
+
(name) => /^(todo|fake|placeholder|example)-|does-not-exist| hallucinated/i.test(name)
|
|
7191
|
+
);
|
|
8591
7192
|
}
|
|
8592
|
-
function
|
|
8593
|
-
|
|
7193
|
+
function readRecentCommits(repoPath) {
|
|
7194
|
+
try {
|
|
7195
|
+
const output = execFileSync("git", ["log", "--max-count=12", "--format=%H%x00%s"], {
|
|
7196
|
+
cwd: repoPath,
|
|
7197
|
+
encoding: "utf8",
|
|
7198
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7199
|
+
}).trim();
|
|
7200
|
+
if (!output) return [];
|
|
7201
|
+
return output.split("\n").map((line) => {
|
|
7202
|
+
const [sha = "", subject = ""] = line.split("\0");
|
|
7203
|
+
return { sha, subject };
|
|
7204
|
+
}).filter((commit) => commit.sha.length >= 7);
|
|
7205
|
+
} catch {
|
|
7206
|
+
return [];
|
|
7207
|
+
}
|
|
8594
7208
|
}
|
|
8595
|
-
function
|
|
8596
|
-
return (
|
|
8597
|
-
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
) || /(^|\/)docs\/.*(audit|runbook|incident|changelog|security).*\.(md|rst)$/i.test(file) || // Provenance/signed-release tooling config is itself audit-trail evidence (a repo that
|
|
8605
|
-
// wires SLSA/cosign attestation or CITATION.cff is documenting release provenance).
|
|
8606
|
-
/(^|\/)CITATION\.cff$/i.test(file)
|
|
7209
|
+
function readPackageScripts(packageJsonPath) {
|
|
7210
|
+
if (!isRegularFile(packageJsonPath)) return /* @__PURE__ */ new Map();
|
|
7211
|
+
const parsed = parseJsonObject(readFileSync(packageJsonPath, "utf8"));
|
|
7212
|
+
const scripts = parsed?.scripts;
|
|
7213
|
+
if (!isRecord(scripts)) return /* @__PURE__ */ new Map();
|
|
7214
|
+
return new Map(
|
|
7215
|
+
Object.entries(scripts).filter(
|
|
7216
|
+
(entry) => typeof entry[1] === "string"
|
|
7217
|
+
)
|
|
8607
7218
|
);
|
|
8608
7219
|
}
|
|
8609
|
-
function
|
|
8610
|
-
|
|
7220
|
+
function evidenceForRelative(repoPath, path, kind, label) {
|
|
7221
|
+
const fullPath = join(repoPath, path);
|
|
7222
|
+
const contents = isRegularFile(fullPath) ? readFileSync(fullPath, "utf8") : "";
|
|
7223
|
+
return {
|
|
7224
|
+
kind,
|
|
7225
|
+
label,
|
|
7226
|
+
path,
|
|
7227
|
+
...contents ? {
|
|
7228
|
+
line: firstMeaningfulLine(contents),
|
|
7229
|
+
contentHash: createHash2("sha256").update(contents).digest("hex")
|
|
7230
|
+
} : {}
|
|
7231
|
+
};
|
|
8611
7232
|
}
|
|
8612
|
-
function
|
|
8613
|
-
|
|
7233
|
+
function evidenceForRelativeAtLine(repoPath, path, kind, label, line) {
|
|
7234
|
+
const fullPath = join(repoPath, path);
|
|
7235
|
+
const contents = isRegularFile(fullPath) ? readFileSync(fullPath, "utf8") : "";
|
|
7236
|
+
return {
|
|
7237
|
+
kind,
|
|
7238
|
+
label,
|
|
7239
|
+
path,
|
|
7240
|
+
line,
|
|
7241
|
+
...contents ? { contentHash: createHash2("sha256").update(contents).digest("hex") } : {}
|
|
7242
|
+
};
|
|
8614
7243
|
}
|
|
8615
|
-
function
|
|
8616
|
-
return
|
|
7244
|
+
function metric(name, label, value, max, weight, unit, description, kind) {
|
|
7245
|
+
return {
|
|
7246
|
+
name,
|
|
7247
|
+
label,
|
|
7248
|
+
value: Math.max(0, value),
|
|
7249
|
+
max,
|
|
7250
|
+
...kind ? { kind } : {},
|
|
7251
|
+
weight,
|
|
7252
|
+
unit,
|
|
7253
|
+
description
|
|
7254
|
+
};
|
|
8617
7255
|
}
|
|
8618
|
-
function
|
|
8619
|
-
|
|
7256
|
+
function firstMeaningfulLine(contents) {
|
|
7257
|
+
const lines = contents.split("\n");
|
|
7258
|
+
const index = lines.findIndex((line) => line.trim().length > 0);
|
|
7259
|
+
return index === -1 ? 1 : index + 1;
|
|
8620
7260
|
}
|
|
8621
|
-
function
|
|
7261
|
+
function readGitHead(repoPath) {
|
|
7262
|
+
try {
|
|
7263
|
+
return execFileSync("git", ["rev-parse", "HEAD"], {
|
|
7264
|
+
cwd: repoPath,
|
|
7265
|
+
encoding: "utf8",
|
|
7266
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7267
|
+
}).trim();
|
|
7268
|
+
} catch {
|
|
7269
|
+
return null;
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7272
|
+
function hasEnvPathInGitHistory(repoPath) {
|
|
8622
7273
|
try {
|
|
8623
|
-
|
|
7274
|
+
const output = execFileSync(
|
|
7275
|
+
"git",
|
|
7276
|
+
["log", "--all", "--diff-filter=AM", "--name-only", "--format="],
|
|
7277
|
+
{
|
|
7278
|
+
cwd: repoPath,
|
|
7279
|
+
encoding: "utf8",
|
|
7280
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
7281
|
+
maxBuffer: 512e3
|
|
7282
|
+
}
|
|
7283
|
+
).trim();
|
|
7284
|
+
if (!output) return false;
|
|
7285
|
+
return output.split("\n").some((p) => /(?:^|\/)\.env(?:\.|$)/i.test(p.trim()));
|
|
8624
7286
|
} catch {
|
|
8625
7287
|
return false;
|
|
8626
7288
|
}
|
|
8627
7289
|
}
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
7290
|
+
|
|
7291
|
+
// src/witan/public-scan.ts
|
|
7292
|
+
import { resolve as resolve2 } from "path";
|
|
7293
|
+
|
|
7294
|
+
// src/witan/ingest.ts
|
|
7295
|
+
import { readFileSync as readFileSync5, readdirSync as readdirSync2 } from "fs";
|
|
7296
|
+
import { join as join2 } from "path";
|
|
7297
|
+
|
|
7298
|
+
// src/witan/finding-limits.ts
|
|
7299
|
+
var RULE_ID_MAX = 200;
|
|
7300
|
+
var MESSAGE_MAX = 500;
|
|
7301
|
+
var LOCATION_MAX = 700;
|
|
7302
|
+
function clamp(value, max) {
|
|
7303
|
+
if (value.length <= max) return value;
|
|
7304
|
+
const ellipsis = "...";
|
|
7305
|
+
return `${value.slice(0, Math.max(max - ellipsis.length, 0))}${ellipsis}`;
|
|
8632
7306
|
}
|
|
8633
|
-
function
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
7307
|
+
function clampFinding(finding) {
|
|
7308
|
+
return {
|
|
7309
|
+
...finding,
|
|
7310
|
+
ruleId: clamp(finding.ruleId, RULE_ID_MAX),
|
|
7311
|
+
message: clamp(finding.message, MESSAGE_MAX),
|
|
7312
|
+
...finding.location ? { location: clamp(finding.location, LOCATION_MAX) } : {}
|
|
7313
|
+
};
|
|
8637
7314
|
}
|
|
8638
|
-
|
|
8639
|
-
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
7315
|
+
|
|
7316
|
+
// src/witan/generic-adapter.ts
|
|
7317
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
7318
|
+
var VALID_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
7319
|
+
"A1",
|
|
7320
|
+
"A2",
|
|
7321
|
+
"A3",
|
|
7322
|
+
"A4",
|
|
7323
|
+
"A5",
|
|
7324
|
+
"B1",
|
|
7325
|
+
"B2",
|
|
7326
|
+
"B3",
|
|
7327
|
+
"B4",
|
|
7328
|
+
"B5",
|
|
7329
|
+
"B6"
|
|
7330
|
+
]);
|
|
7331
|
+
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning", "info"]);
|
|
7332
|
+
function isGenericSignalDocument(raw) {
|
|
7333
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
7334
|
+
const doc = raw;
|
|
7335
|
+
return typeof doc.tool === "string" && doc.tool.length > 0 && Array.isArray(doc.signals);
|
|
7336
|
+
}
|
|
7337
|
+
function parseGenericJson(raw) {
|
|
7338
|
+
if (!isGenericSignalDocument(raw)) return [];
|
|
7339
|
+
const source = raw.tool ?? "unknown";
|
|
7340
|
+
const signals = [];
|
|
7341
|
+
for (const signal of raw.signals ?? []) {
|
|
7342
|
+
const dimension = signal.dimension;
|
|
7343
|
+
if (!dimension || !VALID_DIMENSIONS.has(dimension)) continue;
|
|
7344
|
+
const weight = typeof signal.weight === "number" && Number.isFinite(signal.weight) ? Math.min(Math.max(signal.weight, 0), 1) : 0.5;
|
|
7345
|
+
const findings = [];
|
|
7346
|
+
for (const finding of signal.findings ?? []) {
|
|
7347
|
+
const severity = finding.severity;
|
|
7348
|
+
if (!severity || !VALID_SEVERITIES.has(severity)) continue;
|
|
7349
|
+
const ruleId = finding.ruleId ?? "unknown";
|
|
7350
|
+
findings.push({
|
|
7351
|
+
ruleId,
|
|
7352
|
+
severity,
|
|
7353
|
+
message: finding.message ?? ruleId,
|
|
7354
|
+
...finding.location ? { location: finding.location } : {}
|
|
7355
|
+
});
|
|
7356
|
+
}
|
|
7357
|
+
if (findings.length === 0) continue;
|
|
7358
|
+
signals.push({ source, dimension, weight, findings });
|
|
7359
|
+
}
|
|
7360
|
+
return signals;
|
|
7361
|
+
}
|
|
7362
|
+
|
|
7363
|
+
// src/witan/sarif-adapter.ts
|
|
7364
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
7365
|
+
var DIMENSION_RULES = [
|
|
7366
|
+
// A2 — injection / secrets / auth (high weight)
|
|
7367
|
+
{
|
|
7368
|
+
pattern: /sql[- _]?inject|cwe-89|sqli|command[- _]?inject|cwe-78|os[- _]?cmd|rce|remote[- _]?code/i,
|
|
7369
|
+
dimension: "A2",
|
|
7370
|
+
weight: 0.9
|
|
7371
|
+
},
|
|
7372
|
+
{
|
|
7373
|
+
pattern: /secret|credential|api[- _]?key|password[- _]?leak|hardcoded[- _]?(token|key|secret)|cwe-259|cwe-798/i,
|
|
7374
|
+
dimension: "A2",
|
|
7375
|
+
weight: 0.9
|
|
7376
|
+
},
|
|
7377
|
+
{
|
|
7378
|
+
pattern: /path[- _]?traversal|directory[- _]?traversal|cwe-22|lfi|rfi/i,
|
|
7379
|
+
dimension: "A2",
|
|
7380
|
+
weight: 0.8
|
|
7381
|
+
},
|
|
7382
|
+
{
|
|
7383
|
+
pattern: /ssrf|server[- _]?side[- _]?request[- _]?forg|cwe-918/i,
|
|
7384
|
+
dimension: "A2",
|
|
7385
|
+
weight: 0.8
|
|
7386
|
+
},
|
|
7387
|
+
{
|
|
7388
|
+
pattern: /xxe|xml[- _]?external[- _]?entity|cwe-611/i,
|
|
7389
|
+
dimension: "A2",
|
|
7390
|
+
weight: 0.8
|
|
7391
|
+
},
|
|
7392
|
+
{
|
|
7393
|
+
pattern: /auth[- _]?bypass|broken[- _]?auth|missing[- _]?auth|cwe-287|cwe-306|cwe-863|cwe-862/i,
|
|
7394
|
+
dimension: "A2",
|
|
7395
|
+
weight: 0.7
|
|
7396
|
+
},
|
|
7397
|
+
{
|
|
7398
|
+
pattern: /xss|cross[- _]?site[- _]?script|cwe-79/i,
|
|
7399
|
+
dimension: "A2",
|
|
7400
|
+
weight: 0.6
|
|
7401
|
+
},
|
|
7402
|
+
// A4 — dependency vulnerabilities
|
|
7403
|
+
{
|
|
7404
|
+
pattern: /cve-\d{4}-\d+|supply[- _]?chain|depend[a-z]*[- _]?vulner|outdated[- _]?depend|deprecated[- _]?package/i,
|
|
7405
|
+
dimension: "A4",
|
|
7406
|
+
weight: 0.8
|
|
7407
|
+
},
|
|
7408
|
+
{
|
|
7409
|
+
pattern: /npm[- _]?audit|yarn[- _]?audit|pnpm[- _]?audit|pip[- _]?audit|cargo[- _]?audit/i,
|
|
7410
|
+
dimension: "A4",
|
|
7411
|
+
weight: 0.7
|
|
7412
|
+
},
|
|
7413
|
+
// A3 — production readiness / insecure config
|
|
7414
|
+
{
|
|
7415
|
+
pattern: /insecure[- _]?tls|weak[- _]?cipher|tls[- _]?version|http[- _]?strict|hsts|csp[- _]?missing|cwe-326|cwe-327/i,
|
|
7416
|
+
dimension: "A3",
|
|
7417
|
+
weight: 0.5
|
|
7418
|
+
},
|
|
7419
|
+
{
|
|
7420
|
+
pattern: /error[- _]?handl|unhandled[- _]?exception|crash|uncaught|stacktrace[- _]?leak/i,
|
|
7421
|
+
dimension: "A3",
|
|
7422
|
+
weight: 0.4
|
|
7423
|
+
},
|
|
7424
|
+
{
|
|
7425
|
+
pattern: /debug[- _]?mode|dev[- _]?endpoint|staging[- _]?secret/i,
|
|
7426
|
+
dimension: "A3",
|
|
7427
|
+
weight: 0.4
|
|
7428
|
+
},
|
|
7429
|
+
// A1 — test integrity (low weight; SARIF rarely surfaces this)
|
|
7430
|
+
{
|
|
7431
|
+
pattern: /skipped[- _]?test|hollow[- _]?test|empty[- _]?assert|no[- _]?assertion/i,
|
|
7432
|
+
dimension: "A1",
|
|
7433
|
+
weight: 0.2
|
|
8646
7434
|
}
|
|
8647
|
-
|
|
7435
|
+
];
|
|
7436
|
+
var DEFAULT_DIMENSION = "A2";
|
|
7437
|
+
var DEFAULT_WEIGHT = 0.3;
|
|
7438
|
+
var DROP_LEVEL = /* @__PURE__ */ new Set(["none"]);
|
|
7439
|
+
function mapLevel(level) {
|
|
7440
|
+
if (!level || DROP_LEVEL.has(level)) return null;
|
|
7441
|
+
if (level === "error") return "critical";
|
|
7442
|
+
if (level === "warning") return "warning";
|
|
7443
|
+
return "info";
|
|
8648
7444
|
}
|
|
8649
|
-
function
|
|
8650
|
-
const
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
for (const entry of historyEntries) {
|
|
8654
|
-
if (scannedFiles >= HISTORY_SECRET_SCAN_CREDENTIAL_BLOB_LIMIT) {
|
|
8655
|
-
return { evidence: null, envPathEvidence, truncated: true };
|
|
8656
|
-
}
|
|
8657
|
-
scannedFiles += 1;
|
|
8658
|
-
const contents = readGitBlob(repoPath, entry.commit, entry.path);
|
|
8659
|
-
if (!contents) continue;
|
|
8660
|
-
if (containsRealSecret(contents)) {
|
|
8661
|
-
return {
|
|
8662
|
-
evidence: {
|
|
8663
|
-
kind: "secret_scan",
|
|
8664
|
-
label: "Committed secret in recent git history",
|
|
8665
|
-
path: entry.path,
|
|
8666
|
-
contentHash: entry.commit
|
|
8667
|
-
},
|
|
8668
|
-
envPathEvidence,
|
|
8669
|
-
truncated: false
|
|
8670
|
-
};
|
|
8671
|
-
}
|
|
8672
|
-
if (!envPathEvidence && isEnvHistoryPath(entry.path)) {
|
|
8673
|
-
envPathEvidence = {
|
|
8674
|
-
kind: "secret_scan",
|
|
8675
|
-
label: ".env file (not a template) tracked in git history; no confirmed secret value found",
|
|
8676
|
-
path: entry.path,
|
|
8677
|
-
contentHash: entry.commit
|
|
8678
|
-
};
|
|
7445
|
+
function mapRuleToDimension(ruleId, rules) {
|
|
7446
|
+
for (const rule of rules) {
|
|
7447
|
+
if (rule.pattern.test(ruleId)) {
|
|
7448
|
+
return { dimension: rule.dimension, weight: rule.weight };
|
|
8679
7449
|
}
|
|
8680
7450
|
}
|
|
8681
|
-
return {
|
|
7451
|
+
return { dimension: DEFAULT_DIMENSION, weight: DEFAULT_WEIGHT };
|
|
8682
7452
|
}
|
|
8683
|
-
function
|
|
8684
|
-
const
|
|
8685
|
-
|
|
8686
|
-
const
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
entries.push(entry);
|
|
8691
|
-
};
|
|
8692
|
-
try {
|
|
8693
|
-
const commits = execFileSync("git", ["rev-list", "--all"], {
|
|
8694
|
-
cwd: repoPath,
|
|
8695
|
-
encoding: "utf8",
|
|
8696
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
8697
|
-
});
|
|
8698
|
-
const output = execFileSync(
|
|
8699
|
-
"git",
|
|
8700
|
-
[
|
|
8701
|
-
"diff-tree",
|
|
8702
|
-
"--stdin",
|
|
8703
|
-
"--root",
|
|
8704
|
-
"--name-only",
|
|
8705
|
-
"-r",
|
|
8706
|
-
"--diff-filter=AM",
|
|
8707
|
-
"--pretty=format:commit:%H"
|
|
8708
|
-
],
|
|
8709
|
-
{
|
|
8710
|
-
cwd: repoPath,
|
|
8711
|
-
encoding: "utf8",
|
|
8712
|
-
input: commits,
|
|
8713
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
8714
|
-
}
|
|
8715
|
-
);
|
|
8716
|
-
let currentCommit = null;
|
|
8717
|
-
for (const line of output.split("\n")) {
|
|
8718
|
-
if (line.startsWith("commit:")) {
|
|
8719
|
-
currentCommit = line.slice("commit:".length);
|
|
8720
|
-
continue;
|
|
8721
|
-
}
|
|
8722
|
-
const path = line.trim();
|
|
8723
|
-
if (!currentCommit || !path) continue;
|
|
8724
|
-
if (!isCredentialHistoryPath(path)) continue;
|
|
8725
|
-
appendEntry({ commit: currentCommit, path });
|
|
8726
|
-
}
|
|
8727
|
-
} catch {
|
|
8728
|
-
}
|
|
8729
|
-
for (const entry of readDeletedCredentialHistoryEntries(repoPath)) {
|
|
8730
|
-
appendEntry(entry);
|
|
8731
|
-
}
|
|
8732
|
-
return entries;
|
|
7453
|
+
function renderLocation(result) {
|
|
7454
|
+
const loc = result.locations?.[0]?.physicalLocation;
|
|
7455
|
+
if (!loc) return void 0;
|
|
7456
|
+
const uri = loc.artifactLocation?.uri;
|
|
7457
|
+
const line = loc.region?.startLine;
|
|
7458
|
+
if (!uri) return void 0;
|
|
7459
|
+
return line != null ? `${uri}:${line}` : uri;
|
|
8733
7460
|
}
|
|
8734
|
-
function
|
|
8735
|
-
const deletedPaths = readDeletedCredentialHistoryPaths(repoPath);
|
|
8736
|
-
const entries = [];
|
|
7461
|
+
function dedupeFindings(findings) {
|
|
8737
7462
|
const seen = /* @__PURE__ */ new Set();
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
}
|
|
8745
|
-
}
|
|
8746
|
-
return entries;
|
|
7463
|
+
return findings.filter((f) => {
|
|
7464
|
+
const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
|
|
7465
|
+
if (seen.has(key)) return false;
|
|
7466
|
+
seen.add(key);
|
|
7467
|
+
return true;
|
|
7468
|
+
});
|
|
8747
7469
|
}
|
|
8748
|
-
function
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
7470
|
+
function parseSarifJson(raw, extraDimensionRules) {
|
|
7471
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
|
|
7472
|
+
const dimensionRules = extraDimensionRules ? [...DIMENSION_RULES, ...extraDimensionRules] : DIMENSION_RULES;
|
|
7473
|
+
const doc = raw;
|
|
7474
|
+
if (!Array.isArray(doc.runs)) return [];
|
|
7475
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
7476
|
+
for (const run of doc.runs) {
|
|
7477
|
+
const driverName = run.tool?.driver?.name ?? "unknown";
|
|
7478
|
+
const source = `sarif:${driverName}`;
|
|
7479
|
+
const ruleDefaultLevels = /* @__PURE__ */ new Map();
|
|
7480
|
+
for (const rule of run.tool?.driver?.rules ?? []) {
|
|
7481
|
+
if (rule.id && rule.defaultConfiguration?.level) {
|
|
7482
|
+
ruleDefaultLevels.set(rule.id, rule.defaultConfiguration.level);
|
|
8757
7483
|
}
|
|
8758
|
-
);
|
|
8759
|
-
const paths = [];
|
|
8760
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8761
|
-
for (const line of output.split("\n")) {
|
|
8762
|
-
if (!line.startsWith("D ")) continue;
|
|
8763
|
-
const path = line.slice(2).trim();
|
|
8764
|
-
if (!path || seen.has(path)) continue;
|
|
8765
|
-
if (!isCredentialHistoryPath(path)) continue;
|
|
8766
|
-
seen.add(path);
|
|
8767
|
-
paths.push(path);
|
|
8768
7484
|
}
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
cwd: repoPath,
|
|
8781
|
-
encoding: "utf8",
|
|
8782
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
7485
|
+
for (const result of run.results ?? []) {
|
|
7486
|
+
const ruleId = result.ruleId ?? "unknown";
|
|
7487
|
+
const effectiveLevel = result.level ?? ruleDefaultLevels.get(ruleId) ?? "warning";
|
|
7488
|
+
const severity = mapLevel(effectiveLevel);
|
|
7489
|
+
if (!severity) continue;
|
|
7490
|
+
const message = result.message?.text ?? ruleId;
|
|
7491
|
+
const location = renderLocation(result);
|
|
7492
|
+
const { dimension, weight } = mapRuleToDimension(ruleId, dimensionRules);
|
|
7493
|
+
const bucketKey = `${source}|${dimension}`;
|
|
7494
|
+
if (!buckets.has(bucketKey)) {
|
|
7495
|
+
buckets.set(bucketKey, { source, dimension, weight, findings: [] });
|
|
8783
7496
|
}
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
} catch {
|
|
8787
|
-
return [];
|
|
8788
|
-
}
|
|
8789
|
-
}
|
|
8790
|
-
function isCredentialHistoryPath(path) {
|
|
8791
|
-
if (isHardExcludedPath(path)) return false;
|
|
8792
|
-
const lowerPath = path.toLowerCase();
|
|
8793
|
-
const basename4 = lowerPath.split("/").at(-1) ?? lowerPath;
|
|
8794
|
-
if (/\.env(?:\.|$)/.test(basename4)) {
|
|
8795
|
-
return true;
|
|
7497
|
+
buckets.get(bucketKey)?.findings.push({ ruleId, severity, message, ...location ? { location } : {} });
|
|
7498
|
+
}
|
|
8796
7499
|
}
|
|
8797
|
-
return
|
|
7500
|
+
return Array.from(buckets.values()).map(({ source, dimension, weight, findings }) => ({
|
|
7501
|
+
source,
|
|
7502
|
+
dimension,
|
|
7503
|
+
weight,
|
|
7504
|
+
findings: dedupeFindings(findings)
|
|
7505
|
+
}));
|
|
8798
7506
|
}
|
|
8799
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
7507
|
+
|
|
7508
|
+
// src/witan/scorecard-adapter.ts
|
|
7509
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
7510
|
+
var CHECK_RULES = {
|
|
7511
|
+
// B2 — PR outcome traceability
|
|
7512
|
+
"Branch-Protection": { dimension: "B2", weight: 0.8 },
|
|
7513
|
+
"Code-Review": { dimension: "B2", weight: 0.7 },
|
|
7514
|
+
// B3 — CI and QA discipline
|
|
7515
|
+
"Dangerous-Workflow": { dimension: "B3", weight: 0.9 },
|
|
7516
|
+
"Token-Permissions": { dimension: "B3", weight: 0.8 },
|
|
7517
|
+
"CI-Tests": { dimension: "B3", weight: 0.7 },
|
|
7518
|
+
Maintained: { dimension: "B3", weight: 0.3 },
|
|
7519
|
+
// B4 — audit trail / release integrity
|
|
7520
|
+
"Signed-Releases": { dimension: "B4", weight: 0.7 },
|
|
7521
|
+
Packaging: { dimension: "B4", weight: 0.4 },
|
|
7522
|
+
"Security-Policy": { dimension: "B4", weight: 0.4 },
|
|
7523
|
+
// A4 — dependency hygiene
|
|
7524
|
+
Vulnerabilities: { dimension: "A4", weight: 0.9 },
|
|
7525
|
+
"Pinned-Dependencies": { dimension: "A4", weight: 0.8 },
|
|
7526
|
+
"Dependency-Update-Tool": { dimension: "A4", weight: 0.6 },
|
|
7527
|
+
// A2 — data-layer / static analysis
|
|
7528
|
+
SAST: { dimension: "A2", weight: 0.7 },
|
|
7529
|
+
"Binary-Artifacts": { dimension: "A2", weight: 0.6 },
|
|
7530
|
+
// A1 — test integrity
|
|
7531
|
+
Fuzzing: { dimension: "A1", weight: 0.3 }
|
|
7532
|
+
};
|
|
7533
|
+
function mapScoreToSeverity(score) {
|
|
7534
|
+
if (score == null || Number.isNaN(score)) return null;
|
|
7535
|
+
if (score < 0) return null;
|
|
7536
|
+
if (score >= 10) return null;
|
|
7537
|
+
if (score <= 3) return "critical";
|
|
7538
|
+
if (score <= 6) return "warning";
|
|
7539
|
+
return "info";
|
|
8803
7540
|
}
|
|
8804
|
-
function
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
7541
|
+
function dedupeFindings2(findings) {
|
|
7542
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7543
|
+
return findings.filter((f) => {
|
|
7544
|
+
const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
|
|
7545
|
+
if (seen.has(key)) return false;
|
|
7546
|
+
seen.add(key);
|
|
7547
|
+
return true;
|
|
7548
|
+
});
|
|
7549
|
+
}
|
|
7550
|
+
function parseScorecardJson(raw) {
|
|
7551
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
|
|
7552
|
+
const doc = raw;
|
|
7553
|
+
if (!Array.isArray(doc.checks)) return [];
|
|
7554
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
7555
|
+
for (const check of doc.checks) {
|
|
7556
|
+
const name = check.name;
|
|
7557
|
+
if (!name) continue;
|
|
7558
|
+
const rule = CHECK_RULES[name];
|
|
7559
|
+
if (!rule) continue;
|
|
7560
|
+
const severity = mapScoreToSeverity(check.score);
|
|
7561
|
+
if (!severity) continue;
|
|
7562
|
+
const scoreText = typeof check.score === "number" ? `${check.score}/10` : "n/a";
|
|
7563
|
+
const message = `${name} (Scorecard ${scoreText}): ${check.reason ?? "weakness detected"}`.slice(0, 500);
|
|
7564
|
+
const location = check.documentation?.url;
|
|
7565
|
+
const bucket = buckets.get(rule.dimension) ?? { weight: 0, findings: [] };
|
|
7566
|
+
bucket.weight = Math.max(bucket.weight, rule.weight);
|
|
7567
|
+
bucket.findings.push({
|
|
7568
|
+
ruleId: `scorecard:${name}`,
|
|
7569
|
+
severity,
|
|
7570
|
+
message,
|
|
7571
|
+
...location ? { location } : {}
|
|
8811
7572
|
});
|
|
8812
|
-
|
|
8813
|
-
return null;
|
|
7573
|
+
buckets.set(rule.dimension, bucket);
|
|
8814
7574
|
}
|
|
7575
|
+
return Array.from(buckets.entries()).map(([dimension, { weight, findings }]) => ({
|
|
7576
|
+
source: "scorecard",
|
|
7577
|
+
dimension,
|
|
7578
|
+
weight,
|
|
7579
|
+
findings: dedupeFindings2(findings)
|
|
7580
|
+
}));
|
|
8815
7581
|
}
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
7582
|
+
|
|
7583
|
+
// src/witan/ingest.ts
|
|
7584
|
+
function looksLikeSarif(raw) {
|
|
7585
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
7586
|
+
return Array.isArray(raw.runs);
|
|
8820
7587
|
}
|
|
8821
|
-
function
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
7588
|
+
function looksLikeScorecard(raw) {
|
|
7589
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
7590
|
+
return Array.isArray(raw.checks);
|
|
7591
|
+
}
|
|
7592
|
+
function countRawEntries(raw) {
|
|
7593
|
+
const obj = raw;
|
|
7594
|
+
if (Array.isArray(obj.runs)) {
|
|
7595
|
+
return obj.runs.reduce((sum, run) => {
|
|
7596
|
+
const results = run.results;
|
|
7597
|
+
return sum + (Array.isArray(results) ? results.length : 0);
|
|
7598
|
+
}, 0);
|
|
8826
7599
|
}
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
if (distinct <= 2 && maxRun / body.length >= 0.8) return true;
|
|
7600
|
+
if (Array.isArray(obj.checks)) return obj.checks.length;
|
|
7601
|
+
if (Array.isArray(obj.signals)) {
|
|
7602
|
+
return obj.signals.reduce((sum, signal) => {
|
|
7603
|
+
const findings = signal.findings;
|
|
7604
|
+
return sum + (Array.isArray(findings) ? findings.length : 0);
|
|
7605
|
+
}, 0);
|
|
8834
7606
|
}
|
|
8835
|
-
return
|
|
8836
|
-
}
|
|
8837
|
-
function isSyntheticFixtureSecretValue(value) {
|
|
8838
|
-
return value.includes("abcdefghijklmnopqrstuvwxyz") || value.includes("0123456789abcdefghijklmnopqrstuvwxyz") || value.includes("abcdefghijklmnopqrstuvwxyz0123456789") || value.includes("abcdefghijklmnopqrst");
|
|
7607
|
+
return 0;
|
|
8839
7608
|
}
|
|
8840
|
-
function
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
const names = [...Object.keys(dependencies), ...Object.keys(devDependencies)];
|
|
8849
|
-
return names.some(
|
|
8850
|
-
(name) => /^(todo|fake|placeholder|example)-|does-not-exist| hallucinated/i.test(name)
|
|
8851
|
-
);
|
|
7609
|
+
function rawToolName(raw) {
|
|
7610
|
+
const obj = raw;
|
|
7611
|
+
if (Array.isArray(obj.runs)) {
|
|
7612
|
+
const firstRun = obj.runs[0];
|
|
7613
|
+
return firstRun?.tool?.driver?.name ?? "unknown";
|
|
7614
|
+
}
|
|
7615
|
+
if (typeof obj.tool === "string" && obj.tool.length > 0) return obj.tool;
|
|
7616
|
+
return "scorecard";
|
|
8852
7617
|
}
|
|
8853
|
-
function
|
|
7618
|
+
function parseIngestFile(filePath) {
|
|
7619
|
+
let raw;
|
|
8854
7620
|
try {
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
}).trim();
|
|
8860
|
-
if (!output) return [];
|
|
8861
|
-
return output.split("\n").map((line) => {
|
|
8862
|
-
const [sha = "", subject = ""] = line.split("\0");
|
|
8863
|
-
return { sha, subject };
|
|
8864
|
-
}).filter((commit) => commit.sha.length >= 7);
|
|
8865
|
-
} catch {
|
|
8866
|
-
return [];
|
|
7621
|
+
raw = JSON.parse(stripBom(readFileSync5(filePath, "utf8")));
|
|
7622
|
+
} catch (error) {
|
|
7623
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7624
|
+
throw new Error(`Cejel: could not parse ingest file as JSON: ${filePath} (${message})`);
|
|
8867
7625
|
}
|
|
7626
|
+
let signals;
|
|
7627
|
+
if (looksLikeSarif(raw)) signals = parseSarifJson(raw);
|
|
7628
|
+
else if (looksLikeScorecard(raw)) signals = parseScorecardJson(raw);
|
|
7629
|
+
else if (isGenericSignalDocument(raw)) signals = parseGenericJson(raw);
|
|
7630
|
+
if (!signals) {
|
|
7631
|
+
throw new Error(
|
|
7632
|
+
`Cejel: unrecognized ingest file format: ${filePath} \u2014 expected SARIF (a "runs" array), OpenSSF Scorecard JSON (a "checks" array), or the generic Cejel external-signal shape (a "tool" string + "signals" array). See the cejel README "Aggregate your scanners".`
|
|
7633
|
+
);
|
|
7634
|
+
}
|
|
7635
|
+
const rawCount = countRawEntries(raw);
|
|
7636
|
+
const mappedCount = signals.reduce((sum, signal) => sum + signal.findings.length, 0);
|
|
7637
|
+
if (rawCount > 0 && mappedCount === 0) {
|
|
7638
|
+
process.stderr.write(
|
|
7639
|
+
`Cejel: ${rawCount} findings from ${rawToolName(raw)} (${filePath}), 0 mapped to trust criteria
|
|
7640
|
+
`
|
|
7641
|
+
);
|
|
7642
|
+
}
|
|
7643
|
+
return signals.map((signal) => ({
|
|
7644
|
+
...signal,
|
|
7645
|
+
findings: signal.findings.map(clampFinding)
|
|
7646
|
+
}));
|
|
8868
7647
|
}
|
|
8869
|
-
function
|
|
8870
|
-
if (!
|
|
8871
|
-
const
|
|
8872
|
-
const
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
|
|
8877
|
-
)
|
|
8878
|
-
);
|
|
8879
|
-
}
|
|
8880
|
-
function evidenceForRelative(repoPath, path, kind, label) {
|
|
8881
|
-
const fullPath = join3(repoPath, path);
|
|
8882
|
-
const contents = isRegularFile(fullPath) ? readFileSync6(fullPath, "utf8") : "";
|
|
8883
|
-
return {
|
|
8884
|
-
kind,
|
|
8885
|
-
label,
|
|
8886
|
-
path,
|
|
8887
|
-
...contents ? {
|
|
8888
|
-
line: firstMeaningfulLine(contents),
|
|
8889
|
-
contentHash: createHash("sha256").update(contents).digest("hex")
|
|
8890
|
-
} : {}
|
|
8891
|
-
};
|
|
8892
|
-
}
|
|
8893
|
-
function evidenceForRelativeAtLine(repoPath, path, kind, label, line) {
|
|
8894
|
-
const fullPath = join3(repoPath, path);
|
|
8895
|
-
const contents = isRegularFile(fullPath) ? readFileSync6(fullPath, "utf8") : "";
|
|
8896
|
-
return {
|
|
8897
|
-
kind,
|
|
8898
|
-
label,
|
|
8899
|
-
path,
|
|
8900
|
-
line,
|
|
8901
|
-
...contents ? { contentHash: createHash("sha256").update(contents).digest("hex") } : {}
|
|
8902
|
-
};
|
|
8903
|
-
}
|
|
8904
|
-
function metric(name, label, value, max, weight, unit, description, kind) {
|
|
8905
|
-
return {
|
|
8906
|
-
name,
|
|
8907
|
-
label,
|
|
8908
|
-
value: Math.max(0, value),
|
|
8909
|
-
max,
|
|
8910
|
-
...kind ? { kind } : {},
|
|
8911
|
-
weight,
|
|
8912
|
-
unit,
|
|
8913
|
-
description
|
|
8914
|
-
};
|
|
8915
|
-
}
|
|
8916
|
-
function firstMeaningfulLine(contents) {
|
|
8917
|
-
const lines = contents.split("\n");
|
|
8918
|
-
const index = lines.findIndex((line) => line.trim().length > 0);
|
|
8919
|
-
return index === -1 ? 1 : index + 1;
|
|
8920
|
-
}
|
|
8921
|
-
function readGitHead(repoPath) {
|
|
7648
|
+
function expandIngestPattern(pattern) {
|
|
7649
|
+
if (!pattern.includes("*")) return [pattern];
|
|
7650
|
+
const lastSlash = pattern.lastIndexOf("/");
|
|
7651
|
+
const dir = lastSlash === -1 ? "." : pattern.slice(0, lastSlash);
|
|
7652
|
+
const filePattern = lastSlash === -1 ? pattern : pattern.slice(lastSlash + 1);
|
|
7653
|
+
const regexSource = filePattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
7654
|
+
const regex = new RegExp(`^${regexSource}$`);
|
|
7655
|
+
let entries;
|
|
8922
7656
|
try {
|
|
8923
|
-
|
|
8924
|
-
cwd: repoPath,
|
|
8925
|
-
encoding: "utf8",
|
|
8926
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
8927
|
-
}).trim();
|
|
7657
|
+
entries = readdirSync2(dir);
|
|
8928
7658
|
} catch {
|
|
8929
|
-
return
|
|
7659
|
+
return [];
|
|
8930
7660
|
}
|
|
7661
|
+
return entries.filter((name) => regex.test(name)).sort().map((name) => join2(dir, name));
|
|
8931
7662
|
}
|
|
8932
|
-
function
|
|
7663
|
+
function discoverIngestInputs(repoPath) {
|
|
7664
|
+
const inputsDir = join2(repoPath, ".cejel", "inputs");
|
|
7665
|
+
let entries;
|
|
8933
7666
|
try {
|
|
8934
|
-
|
|
8935
|
-
"git",
|
|
8936
|
-
["log", "--all", "--diff-filter=AM", "--name-only", "--format="],
|
|
8937
|
-
{
|
|
8938
|
-
cwd: repoPath,
|
|
8939
|
-
encoding: "utf8",
|
|
8940
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
8941
|
-
maxBuffer: 512e3
|
|
8942
|
-
}
|
|
8943
|
-
).trim();
|
|
8944
|
-
if (!output) return false;
|
|
8945
|
-
return output.split("\n").some((p) => /(?:^|\/)\.env(?:\.|$)/i.test(p.trim()));
|
|
7667
|
+
entries = readdirSync2(inputsDir);
|
|
8946
7668
|
} catch {
|
|
8947
|
-
return
|
|
7669
|
+
return [];
|
|
8948
7670
|
}
|
|
7671
|
+
return entries.filter((name) => /\.(sarif|json)$/i.test(name)).sort().map((name) => join2(inputsDir, name));
|
|
8949
7672
|
}
|
|
8950
7673
|
|
|
8951
|
-
//
|
|
7674
|
+
// src/witan/rubric.ts
|
|
8952
7675
|
var WITAN_RUBRIC = [
|
|
8953
7676
|
{
|
|
8954
7677
|
id: "A1",
|
|
@@ -9007,7 +7730,7 @@ var WITAN_RUBRIC = [
|
|
|
9007
7730
|
}
|
|
9008
7731
|
];
|
|
9009
7732
|
|
|
9010
|
-
//
|
|
7733
|
+
// src/witan/scoring.ts
|
|
9011
7734
|
var MAX_SIGNAL_ADJUSTMENT = 0.8;
|
|
9012
7735
|
function createWitanReport(input, inputSignals, rubric = WITAN_RUBRIC) {
|
|
9013
7736
|
const parsedInput = WitanReportInputSchema.parse(input);
|
|
@@ -9080,20 +7803,22 @@ function createWitanReport(input, inputSignals, rubric = WITAN_RUBRIC) {
|
|
|
9080
7803
|
const overallScore = roundScore(
|
|
9081
7804
|
categoryOrder.reduce((sum, category) => sum + (categoryScoreMap[category] ?? 0), 0) / Math.max(categoryOrder.length, 1)
|
|
9082
7805
|
);
|
|
7806
|
+
const abstained = parsedInput.insufficientSourceReason != null;
|
|
9083
7807
|
return WitanReportSchema.parse({
|
|
9084
7808
|
productSlug: parsedInput.productSlug,
|
|
9085
7809
|
productDisplayName: parsedInput.productDisplayName,
|
|
9086
7810
|
repo: parsedInput.repo,
|
|
9087
7811
|
generatedAt: parsedInput.generatedAt,
|
|
9088
7812
|
rubricVersion: parsedInput.rubricVersion,
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
7813
|
+
verdict: abstained ? "insufficient_source" : witanVerdictForScore(overallScore),
|
|
7814
|
+
codeTrustScore: abstained ? null : codeTrustScore,
|
|
7815
|
+
processTrustScore: abstained ? null : processTrustScore,
|
|
7816
|
+
overallScore: abstained ? null : overallScore,
|
|
9092
7817
|
criteria,
|
|
9093
7818
|
...consumedSignals.length > 0 ? { consumedSignals } : {},
|
|
9094
7819
|
// Only surface the full per-category map for rubrics with more than two buckets —
|
|
9095
7820
|
// the default two-category rubric is fully represented by codeTrustScore/processTrustScore.
|
|
9096
|
-
|
|
7821
|
+
...!abstained && categoryOrder.length > 2 ? { categoryScores: categoryScoreMap } : {},
|
|
9097
7822
|
// Pass through repo-archetype metadata verbatim — createWitanReport does not compute or
|
|
9098
7823
|
// alter it (see classifyRepoArchetype in repo-signals.ts); per-criterion scoring above is
|
|
9099
7824
|
// unaffected by archetype, only presentation layers (badge/terminal/verdict) key off it.
|
|
@@ -9315,7 +8040,7 @@ function roundScore(score) {
|
|
|
9315
8040
|
return Math.round(score * 10) / 10;
|
|
9316
8041
|
}
|
|
9317
8042
|
|
|
9318
|
-
//
|
|
8043
|
+
// src/witan/public-scan.ts
|
|
9319
8044
|
function scoreRepoWithPublicCejel(options) {
|
|
9320
8045
|
const input = buildWitanInputFromRepo({
|
|
9321
8046
|
productSlug: options.productSlug,
|
|
@@ -9351,85 +8076,15 @@ function resolvePublicIngestSignals(options) {
|
|
|
9351
8076
|
return files.flatMap((file) => parseIngestFile(file));
|
|
9352
8077
|
}
|
|
9353
8078
|
|
|
9354
|
-
// ../witan/src/repo-clone.ts
|
|
9355
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
9356
|
-
import { mkdirSync, rmSync } from "fs";
|
|
9357
|
-
import { tmpdir } from "os";
|
|
9358
|
-
import { join as join4 } from "path";
|
|
9359
|
-
|
|
9360
|
-
// ../witan/src/cejel-package-name.ts
|
|
9361
|
-
import { readFileSync as readFileSync7 } from "fs";
|
|
9362
|
-
import { fileURLToPath } from "url";
|
|
9363
|
-
|
|
9364
|
-
// ../witan/src/leaderboard.ts
|
|
9365
|
-
var RESERVED_CORPUS_SLUGS = ["biome", "tsconfig", "package"];
|
|
9366
|
-
var LeaderboardCorpusEntrySchema = external_exports.object({
|
|
9367
|
-
// Also the evidence-report slug (reports/<name>.{json,md,svg}) — min length 3
|
|
9368
|
-
// to satisfy the WitanReport productSlug pattern.
|
|
9369
|
-
name: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/).refine((value) => !RESERVED_CORPUS_SLUGS.includes(value), {
|
|
9370
|
-
message: "Corpus entry name collides with a tool config filename (reports/<name>.json would be discovered by that tool) \u2014 pick a different slug, e.g. biomejs."
|
|
9371
|
-
}),
|
|
9372
|
-
category: external_exports.string().min(1).max(80),
|
|
9373
|
-
expectedArchetype: external_exports.string().min(1).max(40),
|
|
9374
|
-
license: external_exports.string().min(1).max(80),
|
|
9375
|
-
/**
|
|
9376
|
-
* Repository visibility — the redaction policy's first-class input
|
|
9377
|
-
* (goal_cejel_redaction_policy_is_verifiability_2026-07-12): a path is
|
|
9378
|
-
* published exactly when the reader can check it (public), and withheld
|
|
9379
|
-
* entirely when they can't (private). FAIL CLOSED: absent or unrecognized
|
|
9380
|
-
* resolves to 'private' via `.catch` rather than throwing or defaulting
|
|
9381
|
-
* open, so a corpus entry can never accidentally publish paths by omission.
|
|
9382
|
-
*/
|
|
9383
|
-
visibility: external_exports.enum(["public", "private"]).catch("private"),
|
|
9384
|
-
url: external_exports.string().url().optional(),
|
|
9385
|
-
/**
|
|
9386
|
-
* Immutable source snapshot for URL entries. A rubric rescore always uses
|
|
9387
|
-
* the same commits; changing one is a separate corpus update.
|
|
9388
|
-
*/
|
|
9389
|
-
commit: external_exports.string().regex(/^[0-9a-f]{40}$/).optional(),
|
|
9390
|
-
self: external_exports.literal(true).optional(),
|
|
9391
|
-
/**
|
|
9392
|
-
* A directory inside THIS repository (relative to its root), for internal
|
|
9393
|
-
* entries that are a sub-package rather than the whole repo (e.g. the public
|
|
9394
|
-
* cejel CLI at packages/witan-cli). Scored locally like "self".
|
|
9395
|
-
*/
|
|
9396
|
-
path: external_exports.string().min(1).max(200).regex(/^[A-Za-z0-9._/-]+$/).refine((value) => !value.startsWith("/") && !value.split("/").includes(".."), {
|
|
9397
|
-
message: 'Corpus entry "path" must be relative and must not traverse upward.'
|
|
9398
|
-
}).optional()
|
|
9399
|
-
}).strict().refine((entry) => (entry.url ? 1 : 0) + (entry.self ? 1 : 0) + (entry.path ? 1 : 0) === 1, {
|
|
9400
|
-
message: 'Corpus entry must have exactly one of "url", "self", or "path".'
|
|
9401
|
-
}).refine((entry) => entry.url ? entry.commit !== void 0 : entry.commit === void 0, {
|
|
9402
|
-
message: 'Every URL corpus entry must declare exactly one immutable 40-character "commit".'
|
|
9403
|
-
});
|
|
9404
|
-
var LeaderboardCorpusSchema = external_exports.object({
|
|
9405
|
-
comment: external_exports.string().min(1),
|
|
9406
|
-
entries: external_exports.array(LeaderboardCorpusEntrySchema).min(1)
|
|
9407
|
-
}).strict().refine(
|
|
9408
|
-
(corpus) => new Set(corpus.entries.map((entry) => entry.name)).size === corpus.entries.length,
|
|
9409
|
-
{ message: "Corpus entry names must be unique." }
|
|
9410
|
-
);
|
|
9411
|
-
|
|
9412
|
-
// ../witan/src/quant-integrity.ts
|
|
9413
|
-
import { readFileSync as readFileSync10 } from "fs";
|
|
9414
|
-
import { join as join8 } from "path";
|
|
9415
|
-
|
|
9416
|
-
// ../witan/src/quant-metrics-grading.ts
|
|
9417
|
-
import { createHash as createHash2 } from "crypto";
|
|
9418
|
-
import { readFileSync as readFileSync9 } from "fs";
|
|
9419
|
-
import { join as join7 } from "path";
|
|
9420
|
-
|
|
9421
|
-
// ../witan/src/quant-run-tier-grading.ts
|
|
9422
|
-
import { createHash as createHash3 } from "crypto";
|
|
9423
|
-
|
|
9424
8079
|
// src/product-identity.ts
|
|
9425
|
-
import { existsSync
|
|
9426
|
-
import { basename as
|
|
8080
|
+
import { existsSync, readFileSync as readFileSync6 } from "fs";
|
|
8081
|
+
import { basename as basename2, join as join3 } from "path";
|
|
9427
8082
|
var SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/;
|
|
9428
8083
|
var FALLBACK_SLUG = "repo";
|
|
9429
8084
|
var FALLBACK_DISPLAY_NAME = "Repository";
|
|
9430
8085
|
function deriveProductIdentity(repoPath) {
|
|
9431
|
-
const packageJsonPath =
|
|
9432
|
-
const raw = readPackageName(packageJsonPath) ??
|
|
8086
|
+
const packageJsonPath = join3(repoPath, "package.json");
|
|
8087
|
+
const raw = readPackageName(packageJsonPath) ?? basename2(repoPath);
|
|
9433
8088
|
const displayName = raw.trim().length > 0 ? raw.trim() : FALLBACK_DISPLAY_NAME;
|
|
9434
8089
|
return {
|
|
9435
8090
|
productSlug: slugify(raw),
|
|
@@ -9437,9 +8092,9 @@ function deriveProductIdentity(repoPath) {
|
|
|
9437
8092
|
};
|
|
9438
8093
|
}
|
|
9439
8094
|
function readPackageName(packageJsonPath) {
|
|
9440
|
-
if (!
|
|
8095
|
+
if (!existsSync(packageJsonPath)) return void 0;
|
|
9441
8096
|
try {
|
|
9442
|
-
const parsed = JSON.parse(
|
|
8097
|
+
const parsed = JSON.parse(readFileSync6(packageJsonPath, "utf8"));
|
|
9443
8098
|
if (typeof parsed === "object" && parsed !== null && "name" in parsed) {
|
|
9444
8099
|
const name = parsed.name;
|
|
9445
8100
|
if (typeof name === "string" && name.trim().length > 0) return name;
|
|
@@ -9479,21 +8134,33 @@ function buildWitanCliSummary(report) {
|
|
|
9479
8134
|
).sort();
|
|
9480
8135
|
const externalSources = summarizeExternalSources(report.consumedSignals ?? []);
|
|
9481
8136
|
const allExternalFindings = collectExternalFindings(report.consumedSignals ?? []);
|
|
9482
|
-
|
|
8137
|
+
const common = {
|
|
9483
8138
|
productSlug: report.productSlug,
|
|
9484
8139
|
productDisplayName: report.productDisplayName,
|
|
9485
8140
|
generatedAt: report.generatedAt,
|
|
9486
|
-
overallScore: report.overallScore,
|
|
9487
|
-
codeTrustScore: report.codeTrustScore,
|
|
9488
|
-
processTrustScore: report.processTrustScore,
|
|
9489
|
-
verdict: renderReportVerdict(report),
|
|
9490
8141
|
findingCount: allFindings.length,
|
|
9491
8142
|
topFindings: sorted.slice(0, TOP_FINDINGS_LIMIT),
|
|
9492
8143
|
contributingSources,
|
|
9493
8144
|
externalSources,
|
|
9494
8145
|
externalFindingCount: allExternalFindings.length,
|
|
9495
|
-
topExternalFindings: allExternalFindings.slice(0, EXTERNAL_FINDINGS_DISPLAY_LIMIT)
|
|
9496
|
-
|
|
8146
|
+
topExternalFindings: allExternalFindings.slice(0, EXTERNAL_FINDINGS_DISPLAY_LIMIT)
|
|
8147
|
+
};
|
|
8148
|
+
if (report.verdict === "insufficient_source") {
|
|
8149
|
+
return {
|
|
8150
|
+
...common,
|
|
8151
|
+
overallScore: null,
|
|
8152
|
+
codeTrustScore: null,
|
|
8153
|
+
processTrustScore: null,
|
|
8154
|
+
verdict: "Insufficient source",
|
|
8155
|
+
insufficientSourceReason: report.insufficientSourceReason
|
|
8156
|
+
};
|
|
8157
|
+
}
|
|
8158
|
+
return {
|
|
8159
|
+
...common,
|
|
8160
|
+
overallScore: report.overallScore,
|
|
8161
|
+
codeTrustScore: report.codeTrustScore,
|
|
8162
|
+
processTrustScore: report.processTrustScore,
|
|
8163
|
+
verdict: renderReportVerdict(report)
|
|
9497
8164
|
};
|
|
9498
8165
|
}
|
|
9499
8166
|
|
|
@@ -9515,13 +8182,15 @@ export {
|
|
|
9515
8182
|
__commonJS,
|
|
9516
8183
|
__export,
|
|
9517
8184
|
__toESM,
|
|
9518
|
-
formatExternalSourceLine,
|
|
9519
|
-
renderWitanHtmlReport,
|
|
9520
|
-
renderWitanBadgeEndpoint,
|
|
9521
|
-
renderWitanBadgeSvg,
|
|
9522
8185
|
ZodOptional,
|
|
9523
8186
|
ZodFirstPartyTypeKind,
|
|
9524
8187
|
objectType,
|
|
9525
8188
|
external_exports,
|
|
8189
|
+
formatExternalSourceLine,
|
|
8190
|
+
renderWitanHtmlReport,
|
|
8191
|
+
renderWitanBadgeEndpoint,
|
|
8192
|
+
renderWitanBadgeSvg,
|
|
8193
|
+
serializeWitanReport,
|
|
8194
|
+
createWitanAttestation,
|
|
9526
8195
|
runCejelScan
|
|
9527
8196
|
};
|