@prism-d1/cli 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/dist/assets/github-workflows/prism-agent-eval.yml +2 -1
  2. package/dist/assets/github-workflows/prism-eval-gate-kiro.yml +11 -1
  3. package/dist/assets/gitlab-workflows/prism-eval-gate.yml +8 -0
  4. package/dist/assets/infra/lib/constructs/otel-collector-construct.ts +96 -0
  5. package/dist/assets/infra/lib/dashboard-stack.ts +27 -0
  6. package/dist/assets/infra/lib/lambda/otel-receiver.ts +278 -8
  7. package/dist/assets/infra/lib/lambda/pricing/litellm-snapshot.json +3769 -0
  8. package/dist/assets/infra/lib/lambda/pricing/price-source.ts +56 -0
  9. package/dist/assets/infra/lib/lambda/pricing/price-table.ts +240 -0
  10. package/dist/assets/infra/lib/lambda/pricing/prices-key.ts +6 -0
  11. package/dist/assets/infra/lib/lambda/pricing/reprice.ts +108 -0
  12. package/dist/assets/infra/lib/lambda/pricing-refresh.ts +352 -0
  13. package/dist/assets/infra/lib/lambda/velocity-widget.ts +124 -1
  14. package/dist/assets/infra/package.json +4 -1
  15. package/dist/assets/metric-hooks/prepare-commit-msg +3 -1
  16. package/dist/src/codewatch/config.d.ts +17 -0
  17. package/dist/src/codewatch/config.d.ts.map +1 -0
  18. package/dist/src/codewatch/config.js +40 -0
  19. package/dist/src/codewatch/config.js.map +1 -0
  20. package/dist/src/codewatch/gitleaks.d.ts +49 -0
  21. package/dist/src/codewatch/gitleaks.d.ts.map +1 -0
  22. package/dist/src/codewatch/gitleaks.js +160 -0
  23. package/dist/src/codewatch/gitleaks.js.map +1 -0
  24. package/dist/src/codewatch/globalHooks.d.ts +52 -0
  25. package/dist/src/codewatch/globalHooks.d.ts.map +1 -0
  26. package/dist/src/codewatch/globalHooks.js +235 -0
  27. package/dist/src/codewatch/globalHooks.js.map +1 -0
  28. package/dist/src/codewatch/hooks.d.ts +38 -0
  29. package/dist/src/codewatch/hooks.d.ts.map +1 -0
  30. package/dist/src/codewatch/hooks.js +176 -0
  31. package/dist/src/codewatch/hooks.js.map +1 -0
  32. package/dist/src/codewatch/prepush.d.ts +37 -0
  33. package/dist/src/codewatch/prepush.d.ts.map +1 -0
  34. package/dist/src/codewatch/prepush.js +231 -0
  35. package/dist/src/codewatch/prepush.js.map +1 -0
  36. package/dist/src/codewatch/results.d.ts +90 -0
  37. package/dist/src/codewatch/results.d.ts.map +1 -0
  38. package/dist/src/codewatch/results.js +121 -0
  39. package/dist/src/codewatch/results.js.map +1 -0
  40. package/dist/src/codewatch/reviewers/claude.d.ts +9 -0
  41. package/dist/src/codewatch/reviewers/claude.d.ts.map +1 -0
  42. package/dist/src/codewatch/reviewers/claude.js +48 -0
  43. package/dist/src/codewatch/reviewers/claude.js.map +1 -0
  44. package/dist/src/codewatch/reviewers/index.d.ts +39 -0
  45. package/dist/src/codewatch/reviewers/index.d.ts.map +1 -0
  46. package/dist/src/codewatch/reviewers/index.js +97 -0
  47. package/dist/src/codewatch/reviewers/index.js.map +1 -0
  48. package/dist/src/codewatch/reviewers/kiro.d.ts +14 -0
  49. package/dist/src/codewatch/reviewers/kiro.d.ts.map +1 -0
  50. package/dist/src/codewatch/reviewers/kiro.js +32 -0
  51. package/dist/src/codewatch/reviewers/kiro.js.map +1 -0
  52. package/dist/src/codewatch/reviewers/types.d.ts +56 -0
  53. package/dist/src/codewatch/reviewers/types.d.ts.map +1 -0
  54. package/dist/src/codewatch/reviewers/types.js +91 -0
  55. package/dist/src/codewatch/reviewers/types.js.map +1 -0
  56. package/dist/src/codewatch/rules.d.ts +12 -0
  57. package/dist/src/codewatch/rules.d.ts.map +1 -0
  58. package/dist/src/codewatch/rules.js +27 -0
  59. package/dist/src/codewatch/rules.js.map +1 -0
  60. package/dist/src/commands/_top/dashboard.d.ts +17 -0
  61. package/dist/src/commands/_top/dashboard.d.ts.map +1 -0
  62. package/dist/src/commands/_top/dashboard.js +76 -0
  63. package/dist/src/commands/_top/dashboard.js.map +1 -0
  64. package/dist/src/commands/bedrock-protection/scan-account.d.ts.map +1 -1
  65. package/dist/src/commands/bedrock-protection/scan-account.js +2 -1
  66. package/dist/src/commands/bedrock-protection/scan-account.js.map +1 -1
  67. package/dist/src/commands/bedrock-protection/scan-org.d.ts.map +1 -1
  68. package/dist/src/commands/bedrock-protection/scan-org.js +16 -4
  69. package/dist/src/commands/bedrock-protection/scan-org.js.map +1 -1
  70. package/dist/src/commands/bootstrapper/install-eval-harness.d.ts.map +1 -1
  71. package/dist/src/commands/bootstrapper/install-eval-harness.js +15 -48
  72. package/dist/src/commands/bootstrapper/install-eval-harness.js.map +1 -1
  73. package/dist/src/commands/bootstrapper/install-git-hooks.d.ts +13 -0
  74. package/dist/src/commands/bootstrapper/install-git-hooks.d.ts.map +1 -1
  75. package/dist/src/commands/bootstrapper/install-git-hooks.js +28 -147
  76. package/dist/src/commands/bootstrapper/install-git-hooks.js.map +1 -1
  77. package/dist/src/commands/bootstrapper/setup-otel-sync.d.ts.map +1 -1
  78. package/dist/src/commands/bootstrapper/setup-otel-sync.js +5 -39
  79. package/dist/src/commands/bootstrapper/setup-otel-sync.js.map +1 -1
  80. package/dist/src/commands/codewatch/pre-commit.d.ts +7 -0
  81. package/dist/src/commands/codewatch/pre-commit.d.ts.map +1 -0
  82. package/dist/src/commands/codewatch/pre-commit.js +30 -0
  83. package/dist/src/commands/codewatch/pre-commit.js.map +1 -0
  84. package/dist/src/commands/codewatch/pre-push.d.ts +16 -0
  85. package/dist/src/commands/codewatch/pre-push.d.ts.map +1 -0
  86. package/dist/src/commands/codewatch/pre-push.js +32 -0
  87. package/dist/src/commands/codewatch/pre-push.js.map +1 -0
  88. package/dist/src/commands/codewatch/report.d.ts +22 -0
  89. package/dist/src/commands/codewatch/report.d.ts.map +1 -0
  90. package/dist/src/commands/codewatch/report.js +64 -0
  91. package/dist/src/commands/codewatch/report.js.map +1 -0
  92. package/dist/src/commands/enable/codewatch.d.ts +15 -0
  93. package/dist/src/commands/enable/codewatch.d.ts.map +1 -0
  94. package/dist/src/commands/enable/codewatch.js +186 -0
  95. package/dist/src/commands/enable/codewatch.js.map +1 -0
  96. package/dist/src/commands/git/claude-session-context.d.ts.map +1 -1
  97. package/dist/src/commands/git/claude-session-context.js +2 -1
  98. package/dist/src/commands/git/claude-session-context.js.map +1 -1
  99. package/dist/src/commands/git/commit-trailers.js +1 -1
  100. package/dist/src/commands/git/commit-trailers.js.map +1 -1
  101. package/dist/src/commands/workshop/verify-setup.d.ts.map +1 -1
  102. package/dist/src/commands/workshop/verify-setup.js +5 -3
  103. package/dist/src/commands/workshop/verify-setup.js.map +1 -1
  104. package/dist/src/dashboard/codewatch.d.ts +106 -0
  105. package/dist/src/dashboard/codewatch.d.ts.map +1 -0
  106. package/dist/src/dashboard/codewatch.js +119 -0
  107. package/dist/src/dashboard/codewatch.js.map +1 -0
  108. package/dist/src/dashboard/commits.d.ts +96 -0
  109. package/dist/src/dashboard/commits.d.ts.map +1 -0
  110. package/dist/src/dashboard/commits.js +207 -0
  111. package/dist/src/dashboard/commits.js.map +1 -0
  112. package/dist/src/dashboard/page.d.ts +10 -0
  113. package/dist/src/dashboard/page.d.ts.map +1 -0
  114. package/dist/src/dashboard/page.js +315 -0
  115. package/dist/src/dashboard/page.js.map +1 -0
  116. package/dist/src/dashboard/payload.d.ts +111 -0
  117. package/dist/src/dashboard/payload.d.ts.map +1 -0
  118. package/dist/src/dashboard/payload.js +93 -0
  119. package/dist/src/dashboard/payload.js.map +1 -0
  120. package/dist/src/dashboard/report.d.ts +99 -0
  121. package/dist/src/dashboard/report.d.ts.map +1 -0
  122. package/dist/src/dashboard/report.js +300 -0
  123. package/dist/src/dashboard/report.js.map +1 -0
  124. package/dist/src/dashboard/repos.d.ts +58 -0
  125. package/dist/src/dashboard/repos.d.ts.map +1 -0
  126. package/dist/src/dashboard/repos.js +111 -0
  127. package/dist/src/dashboard/repos.js.map +1 -0
  128. package/dist/src/dashboard/server.d.ts +52 -0
  129. package/dist/src/dashboard/server.d.ts.map +1 -0
  130. package/dist/src/dashboard/server.js +163 -0
  131. package/dist/src/dashboard/server.js.map +1 -0
  132. package/dist/src/dashboard/setup.d.ts +52 -0
  133. package/dist/src/dashboard/setup.d.ts.map +1 -0
  134. package/dist/src/dashboard/setup.js +129 -0
  135. package/dist/src/dashboard/setup.js.map +1 -0
  136. package/dist/src/dashboard/usage.d.ts +43 -0
  137. package/dist/src/dashboard/usage.d.ts.map +1 -0
  138. package/dist/src/dashboard/usage.js +88 -0
  139. package/dist/src/dashboard/usage.js.map +1 -0
  140. package/dist/src/index.d.ts +1 -0
  141. package/dist/src/index.d.ts.map +1 -1
  142. package/dist/src/index.js +40 -1
  143. package/dist/src/index.js.map +1 -1
  144. package/dist/src/utils/audit-bedrock.d.ts +1 -0
  145. package/dist/src/utils/audit-bedrock.d.ts.map +1 -1
  146. package/dist/src/utils/audit-bedrock.js +133 -0
  147. package/dist/src/utils/audit-bedrock.js.map +1 -1
  148. package/dist/src/utils/audit-org.d.ts +1 -0
  149. package/dist/src/utils/audit-org.d.ts.map +1 -1
  150. package/dist/src/utils/audit-org.js +155 -0
  151. package/dist/src/utils/audit-org.js.map +1 -1
  152. package/dist/src/utils/otel-sync-schedule.d.ts +22 -0
  153. package/dist/src/utils/otel-sync-schedule.d.ts.map +1 -0
  154. package/dist/src/utils/otel-sync-schedule.js +68 -0
  155. package/dist/src/utils/otel-sync-schedule.js.map +1 -0
  156. package/dist/src/utils/tool-check.d.ts +14 -0
  157. package/dist/src/utils/tool-check.d.ts.map +1 -0
  158. package/dist/src/utils/tool-check.js +42 -0
  159. package/dist/src/utils/tool-check.js.map +1 -0
  160. package/package.json +3 -2
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Codewatch panel data, from `.prism/results/` (see codewatch/results.ts).
3
+ */
4
+ import { readResultEntries, REASON_GITLEAKS_MISSING, countBySeverity } from '../codewatch/results.js';
5
+ import { gitleaksInstallHint } from './setup.js';
6
+ import { localDate } from './usage.js';
7
+ import { collectCommits } from './commits.js';
8
+ export const DEFAULT_TREND_RUNS = 20;
9
+ /** Cap on findings listed per repo, so one noisy branch cannot flood the page. */
10
+ export const MAX_FINDINGS = 200;
11
+ export const MAX_SCANS = 20;
12
+ const isMissingSkip = (r) => r.kind === 'secrets' && r.hook === 'pre-commit' && r.status === 'skipped' && r.reason === REASON_GITLEAKS_MISSING;
13
+ /** A pre-commit that actually ran gitleaks (any verdict). */
14
+ const ranGitleaks = (r) => r.kind === 'secrets' && r.hook === 'pre-commit' && (r.status === 'ok' || r.status === 'findings' || (r.status === 'error' && !/not on PATH/.test(r.reason || '')));
15
+ /** Local calendar day, so the banner reads "since 2026-11-03". */
16
+ function day(iso) {
17
+ const d = new Date(iso);
18
+ return Number.isNaN(d.getTime()) ? iso.slice(0, 10) : localDate(d);
19
+ }
20
+ function bannerText(gitleaksAvailable, count, since) {
21
+ if (gitleaksAvailable)
22
+ return null;
23
+ return count
24
+ ? `Secret scanning is off: gitleaks is not installed. ${count} commit${count === 1 ? '' : 's'} since ${day(since)} ${count === 1 ? 'was' : 'were'} not scanned.`
25
+ : 'Secret scanning is off: gitleaks is not installed. No unscanned commits recorded yet.';
26
+ }
27
+ export function secretScanning(sorted, gitleaksAvailable, hint = gitleaksInstallHint()) {
28
+ let lastRan = -1;
29
+ sorted.forEach((r, i) => { if (ranGitleaks(r))
30
+ lastRan = i; });
31
+ const streak = sorted.slice(lastRan + 1).filter(isMissingSkip);
32
+ const since = streak.length ? streak[0].started_at : null;
33
+ return { gitleaksAvailable, unscannedCommits: streak.length, unscannedSince: since, installHint: hint, banner: bannerText(gitleaksAvailable, streak.length, since) };
34
+ }
35
+ /**
36
+ * gitleaks is a machine tool, so the banner is machine-level: it sums each
37
+ * repo's unscanned commits and dates them from the earliest.
38
+ */
39
+ export function combineSecretScanning(perRepo, gitleaksAvailable, hint = gitleaksInstallHint()) {
40
+ const count = perRepo.reduce((n, s) => n + s.unscannedCommits, 0);
41
+ const since = perRepo.map((s) => s.unscannedSince).filter((x) => !!x).sort()[0] ?? null;
42
+ return { gitleaksAvailable, unscannedCommits: count, unscannedSince: since, installHint: hint, banner: bannerText(gitleaksAvailable, count, since) };
43
+ }
44
+ function summarize(r) {
45
+ const c = countBySeverity(r.findings || []);
46
+ return {
47
+ started_at: r.started_at, kind: r.kind, hook: r.hook, status: r.status, tool: r.tool, model: r.model ?? null,
48
+ commit: r.commit ?? null, branch: r.branch ?? null, high: c.high, medium: c.medium, low: c.low, reason: r.reason ?? null,
49
+ };
50
+ }
51
+ /**
52
+ * A pre-commit run that stopped a commit: a finding, or a scan that ran but
53
+ * gave no verdict. A missing gitleaks is an error that did NOT block.
54
+ */
55
+ function isBlock(r) {
56
+ if (r.kind !== 'secrets' || r.hook !== 'pre-commit')
57
+ return false;
58
+ if (r.status === 'findings')
59
+ return true;
60
+ return r.status === 'error' && !/not on PATH/.test(r.reason || '');
61
+ }
62
+ const byTime = (a, b) => String(a.started_at).localeCompare(String(b.started_at));
63
+ export function collectCodewatch(repoRoot, trendRuns = DEFAULT_TREND_RUNS, gitleaksAvailable = true) {
64
+ const entries = readResultEntries(repoRoot).filter((e) => e.result && typeof e.result.started_at === 'string');
65
+ const idOf = new Map(entries.map((e) => [e.result, e.id]));
66
+ const all = entries.map((e) => e.result).sort(byTime);
67
+ const latest = new Map();
68
+ const latestReview = new Map();
69
+ for (const r of all) {
70
+ const branch = r.branch || '(detached)';
71
+ const entry = latest.get(branch) || { branch, review: null, secrets: null };
72
+ if (r.kind === 'review' && r.hook === 'pre-push') {
73
+ entry.review = summarize(r);
74
+ latestReview.set(branch, r);
75
+ }
76
+ if (r.kind === 'secrets' && r.hook === 'pre-commit')
77
+ entry.secrets = summarize(r);
78
+ latest.set(branch, entry);
79
+ }
80
+ const findings = [];
81
+ for (const r of latestReview.values()) {
82
+ for (const f of r.findings || [])
83
+ findings.push({ ...f, branch: r.branch, commit: r.commit, tool: r.tool, started_at: r.started_at });
84
+ }
85
+ const order = { high: 0, medium: 1, low: 2 };
86
+ findings.sort((a, b) => order[a.severity] - order[b.severity] || a.file.localeCompare(b.file) || (a.line ?? 0) - (b.line ?? 0));
87
+ const bySeverity = { high: 0, medium: 0, low: 0 };
88
+ const byCategory = { quality: 0, security: 0 };
89
+ for (const f of findings) {
90
+ bySeverity[f.severity]++;
91
+ byCategory[f.category]++;
92
+ }
93
+ const reviews = all.filter((r) => r.kind === 'review' && r.tool && r.tool !== 'none');
94
+ const allReviews = all.filter((r) => r.kind === 'review' && r.hook === 'pre-push');
95
+ const lastReview = allReviews.length ? allReviews[allReviews.length - 1] : null;
96
+ return {
97
+ hasResults: all.length > 0,
98
+ lastRunAt: all.length ? all[all.length - 1].started_at : null,
99
+ lastReviewer: reviews.length ? reviews[reviews.length - 1].tool : null,
100
+ lastReviewId: lastReview ? idOf.get(lastReview) ?? null : null,
101
+ scans: allReviews.slice(-MAX_SCANS).reverse().map((r) => {
102
+ const c = countBySeverity(r.findings || []);
103
+ return { id: idOf.get(r), started_at: r.started_at, branch: r.branch ?? null, tool: r.tool, model: r.model ?? null, status: r.status, high: c.high, medium: c.medium, low: c.low, reason: r.reason ?? null };
104
+ }),
105
+ totalRuns: all.length,
106
+ latestByBranch: [...latest.values()].sort((a, b) => a.branch.localeCompare(b.branch)),
107
+ findings: findings.slice(0, MAX_FINDINGS),
108
+ findingsTruncated: findings.length > MAX_FINDINGS,
109
+ bySeverity,
110
+ byCategory,
111
+ gitleaksBlocks: all.filter(isBlock).map(summarize).reverse(),
112
+ // --no-verify and other unhooked commits; gitleaks-missing ones are counted in secretScanning.
113
+ skipped: all.filter((r) => r.kind === 'secrets' && r.status === 'skipped' && !isMissingSkip(r)).map(summarize).reverse(),
114
+ trend: all.filter((r) => r.status !== 'skipped').slice(-trendRuns).map(summarize),
115
+ secretScanning: secretScanning(all, gitleaksAvailable),
116
+ commits: all.length ? collectCommits(repoRoot, all, { idOf: (r) => idOf.get(r) ?? null }) : { rows: [], total: 0, truncated: false, timing: { logMs: 0, blameMs: 0, blameCalls: 0 } },
117
+ };
118
+ }
119
+ //# sourceMappingURL=codewatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codewatch.js","sourceRoot":"","sources":["../../../src/dashboard/codewatch.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAqD,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACzJ,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,cAAc,EAAqB,MAAM,cAAc,CAAC;AAEjE,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC,kFAAkF;AAClF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AA6EhC,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAe5B,MAAM,aAAa,GAAG,CAAC,CAAc,EAAE,EAAE,CACvC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,uBAAuB,CAAC;AAEpH,6DAA6D;AAC7D,MAAM,WAAW,GAAG,CAAC,CAAc,EAAE,EAAE,CACrC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAErK,kEAAkE;AAClE,SAAS,GAAG,CAAC,GAAW;IACtB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,UAAU,CAAC,iBAA0B,EAAE,KAAa,EAAE,KAAoB;IACjF,IAAI,iBAAiB;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,KAAK;QACV,CAAC,CAAC,sDAAsD,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU,GAAG,CAAC,KAAM,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,eAAe;QACjK,CAAC,CAAC,uFAAuF,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAqB,EAAE,iBAA0B,EAAE,IAAI,GAAG,mBAAmB,EAAE;IAC5G,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC;IACjB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;AACvK,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAyB,EAAE,iBAA0B,EAAE,IAAI,GAAG,mBAAmB,EAAE;IACvH,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACrG,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,iBAAiB,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;AACvJ,CAAC;AAED,SAAS,SAAS,CAAC,CAAc;IAC/B,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC5C,OAAO;QACL,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI;QAC5G,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI;KACzH,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CAAC,CAAc;IAC7B,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO,KAAK,CAAC;IAClE,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,CAAc,EAAE,CAAc,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;AAE5G,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,SAAS,GAAG,kBAAkB,EAAE,iBAAiB,GAAG,IAAI;IACzG,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC;IAC/G,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC/C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAuB,CAAC;IACpD,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,YAAY,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5E,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAAC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAAC,CAAC;QAC/G,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY;YAAE,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,EAAE;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IACxI,CAAC;IACD,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAW,CAAC;IACtD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IAEhI,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAClD,MAAM,UAAU,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;IAAC,CAAC;IAEjF,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACtF,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IACnF,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChF,OAAO;QACL,UAAU,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC;QAC1B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;QAC7D,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;QACtE,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI;QAC9D,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACtD,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;YAC5C,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAW,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;QACzN,CAAC,CAAC;QACF,SAAS,EAAE,GAAG,CAAC,MAAM;QACrB,cAAc,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACrF,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;QACzC,iBAAiB,EAAE,QAAQ,CAAC,MAAM,GAAG,YAAY;QACjD,UAAU;QACV,UAAU;QACV,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;QAC5D,+FAA+F;QAC/F,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;QACxH,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;QACjF,cAAc,EAAE,cAAc,CAAC,GAAG,EAAE,iBAAiB,CAAC;QACtD,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,EAAE;KACtL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,96 @@
1
+ import { type Finding, type PrismResult } from '../codewatch/results.js';
2
+ export declare const MAX_COMMIT_ROWS = 50;
3
+ /** History read per repo; ranges reaching further are cut there. */
4
+ export declare const LOG_LIMIT = 5000;
5
+ export interface LogEntry {
6
+ sha: string;
7
+ parents: string[];
8
+ tree: string;
9
+ authorDate: string;
10
+ subject: string;
11
+ }
12
+ export interface CommitFinding extends Finding {
13
+ /** blame: the commit introduced this line. tip: blame could not say; shown on the push's tip. */
14
+ attributed: 'blame' | 'tip';
15
+ /** Tip of the push the finding was reported in, when attributed to the tip. */
16
+ inPushOf: string | null;
17
+ }
18
+ export type SecretScanState = 'ok' | 'not-scanned' | 'no-verify' | 'flagged' | 'none';
19
+ export type ReviewState = 'clean' | 'findings' | 'failed' | 'not-reviewed';
20
+ export interface CommitRow {
21
+ sha: string;
22
+ short: string;
23
+ /** null when the commit is no longer reachable from any ref (amended, rebased away). */
24
+ subject: string | null;
25
+ inHistory: boolean;
26
+ branch: string | null;
27
+ authorDate: string | null;
28
+ secretScan: {
29
+ state: SecretScanState;
30
+ reason: string | null;
31
+ };
32
+ review: {
33
+ state: ReviewState;
34
+ tool: string | null;
35
+ model: string | null;
36
+ /** Reviews whose range included this commit; the newest one is shown. */
37
+ reviewCount: number;
38
+ reviewedAt: string | null;
39
+ tip: string | null;
40
+ /** Result id of the review shown, for the report link. */
41
+ reportId: string | null;
42
+ high: number;
43
+ medium: number;
44
+ low: number;
45
+ reason: string | null;
46
+ };
47
+ findings: CommitFinding[];
48
+ }
49
+ export interface CommitsPanel {
50
+ rows: CommitRow[];
51
+ total: number;
52
+ truncated: boolean;
53
+ /** Measured cost of building the table. */
54
+ timing: {
55
+ logMs: number;
56
+ blameMs: number;
57
+ blameCalls: number;
58
+ };
59
+ }
60
+ /** One `git log --all` for the repo, newest first. */
61
+ export declare function readLog(repo: string, limit?: number): Map<string, LogEntry>;
62
+ /**
63
+ * Commits a push of `tip` over `base` introduced: `git rev-list base..tip`,
64
+ * computed from the log. With no base, just the tip.
65
+ */
66
+ export declare function expandRange(log: Map<string, LogEntry>, base: string | null, tip: string): string[];
67
+ /** Per-request blame cache: `${tip}\0${file}\0${line}` -> introducing commit or null. */
68
+ export declare class Blamer {
69
+ private repo;
70
+ private cache;
71
+ calls: number;
72
+ ms: number;
73
+ constructor(repo: string);
74
+ blame(tip: string, file: string, line: number | null): string | null;
75
+ }
76
+ export interface CollectCommitsOptions {
77
+ log?: Map<string, LogEntry>;
78
+ blamer?: Blamer;
79
+ maxRows?: number;
80
+ /** Result id lookup, for report links. */
81
+ idOf?: (r: PrismResult) => string | null;
82
+ }
83
+ export interface Attribution {
84
+ /** All commits the push introduced. */
85
+ range: string[];
86
+ /** Findings per commit they were attributed to. */
87
+ byCommit: Map<string, CommitFinding[]>;
88
+ }
89
+ /**
90
+ * Attributes one review's findings to commits: the commit `git blame` names at
91
+ * the review's tip, when it is inside the pushed range; otherwise the tip,
92
+ * marked "in push of <tip>". Shared by the Commits table and the scan report.
93
+ */
94
+ export declare function attributeFindings(rev: PrismResult, log: Map<string, LogEntry>, blamer: Blamer): Attribution;
95
+ export declare function collectCommits(repo: string, results: PrismResult[], opts?: CollectCommitsOptions): CommitsPanel;
96
+ //# sourceMappingURL=commits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commits.d.ts","sourceRoot":"","sources":["../../../src/dashboard/commits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Codewatch results per commit, for the dashboard's Commits table.
3
+ *
4
+ * Results are recorded per hook run, not per commit: a pre-commit scan knows
5
+ * only the staged tree, and a pre-push review covers a range. This module maps
6
+ * both back onto commits:
7
+ *
8
+ * - one `git log --all` per repo gives every commit's parents, tree, author
9
+ * date and subject; review ranges (`base..tip`, the commits the push
10
+ * introduced) are expanded from it in memory, so no per-review rev-list;
11
+ * - pre-commit scans match commits by tree id (a commit's tree is the staged
12
+ * tree it was scanned as);
13
+ * - each review finding is attributed to the commit that introduced its line
14
+ * with `git blame` at the review's tip, once per distinct location; when
15
+ * blame fails or names a commit outside the range, the finding stays on the
16
+ * tip, marked "in push of <tip>".
17
+ */
18
+ import { spawnSync } from 'node:child_process';
19
+ import { REASON_GITLEAKS_MISSING } from '../codewatch/results.js';
20
+ export const MAX_COMMIT_ROWS = 50;
21
+ /** History read per repo; ranges reaching further are cut there. */
22
+ export const LOG_LIMIT = 5000;
23
+ function git(repo, args) {
24
+ const r = spawnSync('git', ['-C', repo, ...args], { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024, stdio: ['ignore', 'pipe', 'ignore'] });
25
+ return { ok: r.status === 0, out: r.stdout || '' };
26
+ }
27
+ const SEP = '\x1f';
28
+ /** One `git log --all` for the repo, newest first. */
29
+ export function readLog(repo, limit = LOG_LIMIT) {
30
+ const r = git(repo, ['log', '--all', `--max-count=${limit}`, `--format=%H${SEP}%P${SEP}%T${SEP}%aI${SEP}%s`]);
31
+ const m = new Map();
32
+ if (!r.ok)
33
+ return m;
34
+ for (const line of r.out.split('\n')) {
35
+ if (!line)
36
+ continue;
37
+ const [sha, parents, tree, authorDate, subject] = line.split(SEP);
38
+ m.set(sha, { sha, parents: parents ? parents.split(' ') : [], tree, authorDate, subject: subject ?? '' });
39
+ }
40
+ return m;
41
+ }
42
+ /** Commits reachable from `sha` within the log (inclusive). */
43
+ function ancestors(log, sha) {
44
+ const seen = new Set();
45
+ const stack = [sha];
46
+ while (stack.length) {
47
+ const c = stack.pop();
48
+ if (seen.has(c) || !log.has(c))
49
+ continue;
50
+ seen.add(c);
51
+ for (const p of log.get(c).parents)
52
+ stack.push(p);
53
+ }
54
+ return seen;
55
+ }
56
+ /**
57
+ * Commits a push of `tip` over `base` introduced: `git rev-list base..tip`,
58
+ * computed from the log. With no base, just the tip.
59
+ */
60
+ export function expandRange(log, base, tip) {
61
+ if (!log.has(tip))
62
+ return [tip];
63
+ if (!base)
64
+ return [tip];
65
+ const exclude = ancestors(log, base);
66
+ return [...ancestors(log, tip)].filter((c) => !exclude.has(c));
67
+ }
68
+ const byTime = (a, b) => String(a.started_at).localeCompare(String(b.started_at));
69
+ /** Per-request blame cache: `${tip}\0${file}\0${line}` -> introducing commit or null. */
70
+ export class Blamer {
71
+ repo;
72
+ cache = new Map();
73
+ calls = 0;
74
+ ms = 0;
75
+ constructor(repo) {
76
+ this.repo = repo;
77
+ }
78
+ blame(tip, file, line) {
79
+ if (!file || !line || line < 1)
80
+ return null;
81
+ const key = `${tip}\0${file}\0${line}`;
82
+ if (this.cache.has(key))
83
+ return this.cache.get(key);
84
+ const t0 = Date.now();
85
+ this.calls++;
86
+ const r = git(this.repo, ['blame', '-l', '-s', '-L', `${line},${line}`, tip, '--', file]);
87
+ this.ms += Date.now() - t0;
88
+ const m = r.ok ? /^\^?([0-9a-f]{40})/.exec(r.out) : null;
89
+ const sha = m ? m[1] : null;
90
+ this.cache.set(key, sha);
91
+ return sha;
92
+ }
93
+ }
94
+ function emptyRow(sha, log) {
95
+ const e = log.get(sha);
96
+ return {
97
+ sha, short: sha.slice(0, 8), subject: e ? e.subject : null, inHistory: !!e, branch: null, authorDate: e ? e.authorDate : null,
98
+ secretScan: { state: 'none', reason: null },
99
+ review: { state: 'not-reviewed', tool: null, model: null, reviewCount: 0, reviewedAt: null, tip: null, reportId: null, high: 0, medium: 0, low: 0, reason: null },
100
+ findings: [],
101
+ };
102
+ }
103
+ /**
104
+ * Attributes one review's findings to commits: the commit `git blame` names at
105
+ * the review's tip, when it is inside the pushed range; otherwise the tip,
106
+ * marked "in push of <tip>". Shared by the Commits table and the scan report.
107
+ */
108
+ export function attributeFindings(rev, log, blamer) {
109
+ const tip = rev.commit;
110
+ const range = expandRange(log, rev.base, tip);
111
+ const inRange = new Set(range);
112
+ const byCommit = new Map();
113
+ for (const f of rev.findings || []) {
114
+ const who = blamer.blame(tip, f.file, f.line);
115
+ const target = who && inRange.has(who) ? who : tip;
116
+ const cf = { ...f, attributed: target === who ? 'blame' : 'tip', inPushOf: target === who ? null : tip };
117
+ if (!byCommit.has(target))
118
+ byCommit.set(target, []);
119
+ byCommit.get(target).push(cf);
120
+ }
121
+ return { range, byCommit };
122
+ }
123
+ export function collectCommits(repo, results, opts = {}) {
124
+ const t0 = Date.now();
125
+ const log = opts.log ?? readLog(repo);
126
+ const logMs = Date.now() - t0;
127
+ const blamer = opts.blamer ?? new Blamer(repo);
128
+ const sorted = results.filter((r) => r && typeof r.started_at === 'string').sort(byTime);
129
+ const rows = new Map();
130
+ const row = (sha) => {
131
+ let r = rows.get(sha);
132
+ if (!r) {
133
+ r = emptyRow(sha, log);
134
+ rows.set(sha, r);
135
+ }
136
+ return r;
137
+ };
138
+ // Pre-push reviews: every commit in each range, newest review wins.
139
+ for (const rev of sorted.filter((r) => r.kind === 'review' && r.hook === 'pre-push' && r.commit)) {
140
+ if (rev.status === 'skipped')
141
+ continue; // nothing was pushed to review
142
+ const tip = rev.commit;
143
+ const { range, byCommit } = attributeFindings(rev, log, blamer);
144
+ for (const sha of range) {
145
+ const r = row(sha);
146
+ const fs = byCommit.get(sha) || [];
147
+ const count = (s) => fs.filter((f) => f.severity === s).length;
148
+ r.branch = rev.branch ?? r.branch;
149
+ r.review = {
150
+ state: rev.status === 'error' ? 'failed' : fs.length ? 'findings' : 'clean',
151
+ tool: rev.tool && rev.tool !== 'none' ? rev.tool : null,
152
+ model: rev.model ?? null,
153
+ reviewCount: r.review.reviewCount + 1,
154
+ reviewedAt: rev.started_at,
155
+ tip,
156
+ high: count('high'), medium: count('medium'), low: count('low'),
157
+ reason: rev.status === 'error' ? rev.reason : null,
158
+ reportId: opts.idOf ? opts.idOf(rev) : null,
159
+ };
160
+ r.findings = fs;
161
+ }
162
+ }
163
+ // Pre-commit scans, matched by tree. Newest scan of a tree wins.
164
+ const scanByTree = new Map();
165
+ for (const s of sorted.filter((r) => r.kind === 'secrets' && r.hook === 'pre-commit' && r.tree))
166
+ scanByTree.set(s.tree, s);
167
+ if (scanByTree.size) {
168
+ for (const e of log.values()) {
169
+ const s = scanByTree.get(e.tree);
170
+ if (!s)
171
+ continue;
172
+ const r = row(e.sha);
173
+ r.branch = r.branch ?? s.branch ?? null;
174
+ if (s.status === 'ok')
175
+ r.secretScan = { state: 'ok', reason: null };
176
+ else if (s.status === 'skipped' && s.reason === REASON_GITLEAKS_MISSING)
177
+ r.secretScan = { state: 'not-scanned', reason: 'gitleaks was not installed' };
178
+ else if (s.status === 'findings')
179
+ r.secretScan = { state: 'flagged', reason: 'committed although the scan found secrets (--no-verify)' };
180
+ else
181
+ r.secretScan = { state: 'not-scanned', reason: s.reason };
182
+ }
183
+ }
184
+ // Commits pre-push found with no pre-commit scan.
185
+ for (const s of sorted.filter((r) => r.kind === 'secrets' && r.hook === 'pre-push' && r.status === 'skipped' && r.commit)) {
186
+ const r = row(s.commit);
187
+ r.branch = r.branch ?? s.branch ?? null;
188
+ if (r.secretScan.state === 'none')
189
+ r.secretScan = { state: 'no-verify', reason: 'pushed with no matching pre-commit scan (--no-verify, rebase or cherry-pick)' };
190
+ }
191
+ // Newest first. Commits made in the same second keep git log order (children
192
+ // before parents); commits no longer in history sort after those that are.
193
+ const order = new Map();
194
+ let i = 0;
195
+ for (const sha of log.keys())
196
+ order.set(sha, i++);
197
+ const pos = (r) => order.get(r.sha) ?? Number.MAX_SAFE_INTEGER;
198
+ const all = [...rows.values()].sort((a, b) => String(b.authorDate ?? b.review.reviewedAt ?? '').localeCompare(String(a.authorDate ?? a.review.reviewedAt ?? '')) || pos(a) - pos(b) || a.sha.localeCompare(b.sha));
199
+ const max = opts.maxRows ?? MAX_COMMIT_ROWS;
200
+ return {
201
+ rows: all.slice(0, max),
202
+ total: all.length,
203
+ truncated: all.length > max,
204
+ timing: { logMs, blameMs: blamer.ms, blameCalls: blamer.calls },
205
+ };
206
+ }
207
+ //# sourceMappingURL=commits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commits.js","sourceRoot":"","sources":["../../../src/dashboard/commits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The dashboard's single-page app: one self-contained HTML document with
3
+ * inline CSS and JS (nonce-gated by the CSP), no CDN and no network fetch
4
+ * other than its own GET /api/data, so it works offline.
5
+ *
6
+ * Every value from the payload is placed with textContent or a DOM attribute;
7
+ * innerHTML is never used for data.
8
+ */
9
+ export declare function renderPage(nonce: string): string;
10
+ //# sourceMappingURL=page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../src/dashboard/page.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA6SH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQhD"}