openpitstop 1.0.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 (274) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +512 -0
  3. package/demo-repo/README.md +24 -0
  4. package/demo-repo/package-lock.json +4483 -0
  5. package/demo-repo/package.json +17 -0
  6. package/demo-repo/src/config.js +5 -0
  7. package/demo-repo/src/db.js +31 -0
  8. package/demo-repo/src/server.js +13 -0
  9. package/demo-repo/src/userController.js +22 -0
  10. package/demo-repo/src/userRepo.js +18 -0
  11. package/demo-repo/src/userService.js +59 -0
  12. package/demo-repo/test/user.test.js +12 -0
  13. package/demo-repo-fintech/README.md +27 -0
  14. package/demo-repo-fintech/package-lock.json +1023 -0
  15. package/demo-repo-fintech/package.json +14 -0
  16. package/demo-repo-fintech/pitstop-repro-ledger-order-ord-conc-1-charged-2.test.mjs +175 -0
  17. package/demo-repo-fintech/pitstop-repro-ledger-order-ord-retry-2-charged-2.test.mjs +175 -0
  18. package/demo-repo-fintech/pitstop-repro-ledger-order-ord-webhook-3-charged-2.test.mjs +175 -0
  19. package/demo-repo-fintech/src/gateway.js +26 -0
  20. package/demo-repo-fintech/src/server.js +61 -0
  21. package/demo-repo-generators/package-lock.json +1508 -0
  22. package/demo-repo-generators/package.json +17 -0
  23. package/demo-repo-generators/public/index.html +10 -0
  24. package/demo-repo-generators/scripts/build.js +17 -0
  25. package/demo-repo-generators/src/counter.js +16 -0
  26. package/demo-repo-integrity/README.md +49 -0
  27. package/demo-repo-integrity/package.json +12 -0
  28. package/demo-repo-integrity/src/money.js +19 -0
  29. package/demo-repo-integrity/test/money.test.js +17 -0
  30. package/dist/analyzers/accessibility.d.ts +18 -0
  31. package/dist/analyzers/accessibility.js +248 -0
  32. package/dist/analyzers/accessibility.js.map +1 -0
  33. package/dist/analyzers/dependencyGraph.d.ts +14 -0
  34. package/dist/analyzers/dependencyGraph.js +206 -0
  35. package/dist/analyzers/dependencyGraph.js.map +1 -0
  36. package/dist/analyzers/devex.d.ts +19 -0
  37. package/dist/analyzers/devex.js +301 -0
  38. package/dist/analyzers/devex.js.map +1 -0
  39. package/dist/analyzers/duplication.d.ts +2 -0
  40. package/dist/analyzers/duplication.js +47 -0
  41. package/dist/analyzers/duplication.js.map +1 -0
  42. package/dist/analyzers/index.d.ts +12 -0
  43. package/dist/analyzers/index.js +38 -0
  44. package/dist/analyzers/index.js.map +1 -0
  45. package/dist/analyzers/integrity/assertionLiteralTamper.d.ts +2 -0
  46. package/dist/analyzers/integrity/assertionLiteralTamper.js +164 -0
  47. package/dist/analyzers/integrity/assertionLiteralTamper.js.map +1 -0
  48. package/dist/analyzers/integrity/exceptionSwallow.d.ts +2 -0
  49. package/dist/analyzers/integrity/exceptionSwallow.js +198 -0
  50. package/dist/analyzers/integrity/exceptionSwallow.js.map +1 -0
  51. package/dist/analyzers/integrity/exitCheat.d.ts +2 -0
  52. package/dist/analyzers/integrity/exitCheat.js +31 -0
  53. package/dist/analyzers/integrity/exitCheat.js.map +1 -0
  54. package/dist/analyzers/integrity/git.d.ts +10 -0
  55. package/dist/analyzers/integrity/git.js +181 -0
  56. package/dist/analyzers/integrity/git.js.map +1 -0
  57. package/dist/analyzers/integrity/hardcodedMatch.d.ts +2 -0
  58. package/dist/analyzers/integrity/hardcodedMatch.js +93 -0
  59. package/dist/analyzers/integrity/hardcodedMatch.js.map +1 -0
  60. package/dist/analyzers/integrity/helpers.d.ts +21 -0
  61. package/dist/analyzers/integrity/helpers.js +66 -0
  62. package/dist/analyzers/integrity/helpers.js.map +1 -0
  63. package/dist/analyzers/integrity/index.d.ts +10 -0
  64. package/dist/analyzers/integrity/index.js +27 -0
  65. package/dist/analyzers/integrity/index.js.map +1 -0
  66. package/dist/analyzers/integrity/mockOverreach.d.ts +2 -0
  67. package/dist/analyzers/integrity/mockOverreach.js +72 -0
  68. package/dist/analyzers/integrity/mockOverreach.js.map +1 -0
  69. package/dist/analyzers/integrity/suppressionCreep.d.ts +2 -0
  70. package/dist/analyzers/integrity/suppressionCreep.js +27 -0
  71. package/dist/analyzers/integrity/suppressionCreep.js.map +1 -0
  72. package/dist/analyzers/integrity/testTamper.d.ts +2 -0
  73. package/dist/analyzers/integrity/testTamper.js +153 -0
  74. package/dist/analyzers/integrity/testTamper.js.map +1 -0
  75. package/dist/analyzers/integrity/types.d.ts +63 -0
  76. package/dist/analyzers/integrity/types.js +13 -0
  77. package/dist/analyzers/integrity/types.js.map +1 -0
  78. package/dist/analyzers/ledger/attacks.d.ts +17 -0
  79. package/dist/analyzers/ledger/attacks.js +135 -0
  80. package/dist/analyzers/ledger/attacks.js.map +1 -0
  81. package/dist/analyzers/ledger/discover.d.ts +15 -0
  82. package/dist/analyzers/ledger/discover.js +122 -0
  83. package/dist/analyzers/ledger/discover.js.map +1 -0
  84. package/dist/analyzers/ledger/evidence.d.ts +22 -0
  85. package/dist/analyzers/ledger/evidence.js +127 -0
  86. package/dist/analyzers/ledger/evidence.js.map +1 -0
  87. package/dist/analyzers/ledger/harness.d.ts +4 -0
  88. package/dist/analyzers/ledger/harness.js +270 -0
  89. package/dist/analyzers/ledger/harness.js.map +1 -0
  90. package/dist/analyzers/ledger/index.d.ts +14 -0
  91. package/dist/analyzers/ledger/index.js +116 -0
  92. package/dist/analyzers/ledger/index.js.map +1 -0
  93. package/dist/analyzers/ledger/types.d.ts +31 -0
  94. package/dist/analyzers/ledger/types.js +2 -0
  95. package/dist/analyzers/ledger/types.js.map +1 -0
  96. package/dist/analyzers/perf.d.ts +2 -0
  97. package/dist/analyzers/perf.js +106 -0
  98. package/dist/analyzers/perf.js.map +1 -0
  99. package/dist/analyzers/reliability.d.ts +22 -0
  100. package/dist/analyzers/reliability.js +339 -0
  101. package/dist/analyzers/reliability.js.map +1 -0
  102. package/dist/analyzers/routes.d.ts +17 -0
  103. package/dist/analyzers/routes.js +115 -0
  104. package/dist/analyzers/routes.js.map +1 -0
  105. package/dist/analyzers/security.d.ts +2 -0
  106. package/dist/analyzers/security.js +302 -0
  107. package/dist/analyzers/security.js.map +1 -0
  108. package/dist/analyzers/suiteRunner.d.ts +64 -0
  109. package/dist/analyzers/suiteRunner.js +381 -0
  110. package/dist/analyzers/suiteRunner.js.map +1 -0
  111. package/dist/analyzers/tests.d.ts +2 -0
  112. package/dist/analyzers/tests.js +215 -0
  113. package/dist/analyzers/tests.js.map +1 -0
  114. package/dist/analyzers/types.d.ts +203 -0
  115. package/dist/analyzers/types.js +2 -0
  116. package/dist/analyzers/types.js.map +1 -0
  117. package/dist/analyzers/util.d.ts +35 -0
  118. package/dist/analyzers/util.js +209 -0
  119. package/dist/analyzers/util.js.map +1 -0
  120. package/dist/ciCheckA.d.ts +2 -0
  121. package/dist/ciCheckA.js +5 -0
  122. package/dist/ciCheckA.js.map +1 -0
  123. package/dist/ciCheckB.d.ts +2 -0
  124. package/dist/ciCheckB.js +6 -0
  125. package/dist/ciCheckB.js.map +1 -0
  126. package/dist/cli.d.ts +2 -0
  127. package/dist/cli.js +65 -0
  128. package/dist/cli.js.map +1 -0
  129. package/dist/commands/budget.d.ts +33 -0
  130. package/dist/commands/budget.js +108 -0
  131. package/dist/commands/budget.js.map +1 -0
  132. package/dist/commands/ci.d.ts +14 -0
  133. package/dist/commands/ci.js +157 -0
  134. package/dist/commands/ci.js.map +1 -0
  135. package/dist/commands/demo.d.ts +2 -0
  136. package/dist/commands/demo.js +163 -0
  137. package/dist/commands/demo.js.map +1 -0
  138. package/dist/commands/digest.d.ts +8 -0
  139. package/dist/commands/digest.js +189 -0
  140. package/dist/commands/digest.js.map +1 -0
  141. package/dist/commands/doctor.d.ts +2 -0
  142. package/dist/commands/doctor.js +98 -0
  143. package/dist/commands/doctor.js.map +1 -0
  144. package/dist/commands/drive.d.ts +3 -0
  145. package/dist/commands/drive.js +170 -0
  146. package/dist/commands/drive.js.map +1 -0
  147. package/dist/commands/gate.d.ts +2 -0
  148. package/dist/commands/gate.js +136 -0
  149. package/dist/commands/gate.js.map +1 -0
  150. package/dist/commands/honesty.d.ts +2 -0
  151. package/dist/commands/honesty.js +182 -0
  152. package/dist/commands/honesty.js.map +1 -0
  153. package/dist/commands/inspect.d.ts +2 -0
  154. package/dist/commands/inspect.js +244 -0
  155. package/dist/commands/inspect.js.map +1 -0
  156. package/dist/commands/install.d.ts +2 -0
  157. package/dist/commands/install.js +81 -0
  158. package/dist/commands/install.js.map +1 -0
  159. package/dist/commands/integrity.d.ts +2 -0
  160. package/dist/commands/integrity.js +74 -0
  161. package/dist/commands/integrity.js.map +1 -0
  162. package/dist/commands/memory.d.ts +6 -0
  163. package/dist/commands/memory.js +90 -0
  164. package/dist/commands/memory.js.map +1 -0
  165. package/dist/commands/pen.d.ts +17 -0
  166. package/dist/commands/pen.js +158 -0
  167. package/dist/commands/pen.js.map +1 -0
  168. package/dist/commands/prompt.d.ts +2 -0
  169. package/dist/commands/prompt.js +37 -0
  170. package/dist/commands/prompt.js.map +1 -0
  171. package/dist/commands/readyCheck.d.ts +21 -0
  172. package/dist/commands/readyCheck.js +68 -0
  173. package/dist/commands/readyCheck.js.map +1 -0
  174. package/dist/commands/report.d.ts +2 -0
  175. package/dist/commands/report.js +48 -0
  176. package/dist/commands/report.js.map +1 -0
  177. package/dist/commands/repro.d.ts +3 -0
  178. package/dist/commands/repro.js +61 -0
  179. package/dist/commands/repro.js.map +1 -0
  180. package/dist/commands/scan.d.ts +27 -0
  181. package/dist/commands/scan.js +348 -0
  182. package/dist/commands/scan.js.map +1 -0
  183. package/dist/commands/share.d.ts +2 -0
  184. package/dist/commands/share.js +163 -0
  185. package/dist/commands/share.js.map +1 -0
  186. package/dist/commands/trends.d.ts +2 -0
  187. package/dist/commands/trends.js +103 -0
  188. package/dist/commands/trends.js.map +1 -0
  189. package/dist/commands/try.d.ts +12 -0
  190. package/dist/commands/try.js +208 -0
  191. package/dist/commands/try.js.map +1 -0
  192. package/dist/commands/verify.d.ts +44 -0
  193. package/dist/commands/verify.js +381 -0
  194. package/dist/commands/verify.js.map +1 -0
  195. package/dist/commands/watch.d.ts +10 -0
  196. package/dist/commands/watch.js +70 -0
  197. package/dist/commands/watch.js.map +1 -0
  198. package/dist/evidence.d.ts +37 -0
  199. package/dist/evidence.js +61 -0
  200. package/dist/evidence.js.map +1 -0
  201. package/dist/graph/correlate.d.ts +7 -0
  202. package/dist/graph/correlate.js +246 -0
  203. package/dist/graph/correlate.js.map +1 -0
  204. package/dist/graph/integrity.d.ts +22 -0
  205. package/dist/graph/integrity.js +39 -0
  206. package/dist/graph/integrity.js.map +1 -0
  207. package/dist/installer/targets.d.ts +23 -0
  208. package/dist/installer/targets.js +162 -0
  209. package/dist/installer/targets.js.map +1 -0
  210. package/dist/memory/store.d.ts +33 -0
  211. package/dist/memory/store.js +131 -0
  212. package/dist/memory/store.js.map +1 -0
  213. package/dist/pen/dynamic.d.ts +36 -0
  214. package/dist/pen/dynamic.js +622 -0
  215. package/dist/pen/dynamic.js.map +1 -0
  216. package/dist/pen/fix.d.ts +35 -0
  217. package/dist/pen/fix.js +239 -0
  218. package/dist/pen/fix.js.map +1 -0
  219. package/dist/pen/proof.d.ts +46 -0
  220. package/dist/pen/proof.js +112 -0
  221. package/dist/pen/proof.js.map +1 -0
  222. package/dist/pen/report.d.ts +11 -0
  223. package/dist/pen/report.js +258 -0
  224. package/dist/pen/report.js.map +1 -0
  225. package/dist/pen/static.d.ts +17 -0
  226. package/dist/pen/static.js +565 -0
  227. package/dist/pen/static.js.map +1 -0
  228. package/dist/pen/store.d.ts +11 -0
  229. package/dist/pen/store.js +36 -0
  230. package/dist/pen/store.js.map +1 -0
  231. package/dist/pen/types.d.ts +112 -0
  232. package/dist/pen/types.js +53 -0
  233. package/dist/pen/types.js.map +1 -0
  234. package/dist/report/format.d.ts +126 -0
  235. package/dist/report/format.js +706 -0
  236. package/dist/report/format.js.map +1 -0
  237. package/dist/report/score.d.ts +47 -0
  238. package/dist/report/score.js +164 -0
  239. package/dist/report/score.js.map +1 -0
  240. package/dist/repro/framework.d.ts +26 -0
  241. package/dist/repro/framework.js +224 -0
  242. package/dist/repro/framework.js.map +1 -0
  243. package/dist/repro/generate.d.ts +14 -0
  244. package/dist/repro/generate.js +669 -0
  245. package/dist/repro/generate.js.map +1 -0
  246. package/dist/repro/ids.d.ts +32 -0
  247. package/dist/repro/ids.js +175 -0
  248. package/dist/repro/ids.js.map +1 -0
  249. package/dist/repro/index.d.ts +24 -0
  250. package/dist/repro/index.js +69 -0
  251. package/dist/repro/index.js.map +1 -0
  252. package/dist/repro/pen.d.ts +26 -0
  253. package/dist/repro/pen.js +321 -0
  254. package/dist/repro/pen.js.map +1 -0
  255. package/dist/repro/run.d.ts +18 -0
  256. package/dist/repro/run.js +36 -0
  257. package/dist/repro/run.js.map +1 -0
  258. package/dist/sandbox/proxy.d.ts +41 -0
  259. package/dist/sandbox/proxy.js +231 -0
  260. package/dist/sandbox/proxy.js.map +1 -0
  261. package/dist/sandbox/startCmd.d.ts +24 -0
  262. package/dist/sandbox/startCmd.js +71 -0
  263. package/dist/sandbox/startCmd.js.map +1 -0
  264. package/dist/ui/spinner.d.ts +18 -0
  265. package/dist/ui/spinner.js +26 -0
  266. package/dist/ui/spinner.js.map +1 -0
  267. package/dist/verify/metrics.d.ts +13 -0
  268. package/dist/verify/metrics.js +72 -0
  269. package/dist/verify/metrics.js.map +1 -0
  270. package/package.json +68 -0
  271. package/scripts/cheat-demo.cjs +102 -0
  272. package/templates/ledger/preload.cjs +331 -0
  273. package/templates/pen/preload.cjs +196 -0
  274. package/templates/pitstop.prompt.md +371 -0
@@ -0,0 +1,112 @@
1
+ /**
2
+ * pen/types.ts — shared types for `pitstop pen`.
3
+ *
4
+ * A pen finding carries its proof with it: the exact attack that was fired
5
+ * (or the static pattern that was matched), the observed response, and any
6
+ * sandbox evidence (outbound host / spawn command). Nothing is asserted
7
+ * without a receipt — that is what separates pen from vibes.
8
+ */
9
+ export type PenConfidence = "proven" | "indicated" | "heuristic";
10
+ export type PenSeverity = "critical" | "high" | "medium" | "low" | "info";
11
+ export interface PenAttackRequest {
12
+ method: string;
13
+ /** Path on the app (without origin), e.g. /api/charge/1 */
14
+ path: string;
15
+ payload?: unknown;
16
+ }
17
+ export interface PenResponseEvidence {
18
+ status?: number;
19
+ /** First ~300 chars of the response body, sanitized. */
20
+ snippet?: string;
21
+ headers?: Record<string, string>;
22
+ }
23
+ export interface PenFinding {
24
+ id: string;
25
+ source: "pen-static" | "pen-dynamic";
26
+ /** xss, sql-injection, missing-auth, ssrf, command-injection, ... */
27
+ type: string;
28
+ severity: PenSeverity;
29
+ confidence: PenConfidence;
30
+ title: string;
31
+ description: string;
32
+ /** Static findings: the file that matched. */
33
+ file?: string;
34
+ line?: number;
35
+ /** Dynamic findings: the route that was attacked. */
36
+ route?: string;
37
+ method?: string;
38
+ /** The exact attack that was fired (dynamic). */
39
+ attack?: PenAttackRequest;
40
+ response?: PenResponseEvidence;
41
+ /** Sandbox evidence: outbound hosts / spawn commands that matched. */
42
+ outbound?: string[];
43
+ /** How a human (or the agent loop) can reproduce it by hand. */
44
+ repro?: string;
45
+ /** Recommended fix, written for a human or an agent to apply. */
46
+ fix?: string;
47
+ /** Set by `--fix` when a deterministic patch was generated. */
48
+ patchFile?: string;
49
+ /**
50
+ * Live-attack verdict for a STATIC finding, applied by the runtime-proof
51
+ * pass after the dynamic phase: "proven" (a canary-class live attack
52
+ * confirmed it), "indicated" (live probing produced class-level signals
53
+ * but no canary), "unproven" (probed with no signal — pattern may be a
54
+ * false positive), "not-tested" (no live probe exists / app did not boot).
55
+ */
56
+ runtimeProof?: "proven" | "indicated" | "unproven" | "not-tested";
57
+ /** Human note explaining the runtime verdict (and the proof it cites). */
58
+ runtimeNote?: string;
59
+ /** For runtime-proven static findings: the dynamic attack class that proved it (e.g. "reflected-xss"). */
60
+ proofType?: string;
61
+ }
62
+ export interface PenDynamicSummary {
63
+ status: "ok" | "aborted" | "skipped";
64
+ note?: string;
65
+ routesProbed: number;
66
+ attacks: number;
67
+ bootMs: number;
68
+ durationMs: number;
69
+ outboundEvents: number;
70
+ }
71
+ export interface PenResult {
72
+ timestamp: string;
73
+ repo: string;
74
+ mode: "pen";
75
+ staticEnabled: boolean;
76
+ dynamicEnabled: boolean;
77
+ dynamic: PenDynamicSummary;
78
+ packages: string[];
79
+ /** Runtime verification of static findings (absent when the dynamic phase was skipped). */
80
+ staticProof?: {
81
+ proven: number;
82
+ indicated: number;
83
+ unproven: number;
84
+ notTested: number;
85
+ };
86
+ findings: PenFinding[];
87
+ summary: {
88
+ critical: number;
89
+ high: number;
90
+ medium: number;
91
+ low: number;
92
+ info: number;
93
+ proven: number;
94
+ indicated: number;
95
+ heuristic: number;
96
+ };
97
+ }
98
+ export declare const SEVERITY_ORDER: PenSeverity[];
99
+ export declare function summarizeFindings(findings: PenFinding[]): PenResult["summary"];
100
+ /** Sort findings: severity first, proven above indicated above heuristic. */
101
+ export declare function sortFindings(findings: PenFinding[]): PenFinding[];
102
+ /** A route inventory entry for the dynamic phase. */
103
+ export interface PenRoute {
104
+ method: string;
105
+ path: string;
106
+ file: string;
107
+ line: number;
108
+ /** True when the path looks sensitive (money/auth/admin). */
109
+ sensitive: boolean;
110
+ /** True when the path is login-ish (rate-limit battery applies). */
111
+ loginLike: boolean;
112
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * pen/types.ts — shared types for `pitstop pen`.
3
+ *
4
+ * A pen finding carries its proof with it: the exact attack that was fired
5
+ * (or the static pattern that was matched), the observed response, and any
6
+ * sandbox evidence (outbound host / spawn command). Nothing is asserted
7
+ * without a receipt — that is what separates pen from vibes.
8
+ */
9
+ export const SEVERITY_ORDER = [
10
+ "critical",
11
+ "high",
12
+ "medium",
13
+ "low",
14
+ "info",
15
+ ];
16
+ export function summarizeFindings(findings) {
17
+ const s = {
18
+ critical: 0,
19
+ high: 0,
20
+ medium: 0,
21
+ low: 0,
22
+ info: 0,
23
+ proven: 0,
24
+ indicated: 0,
25
+ heuristic: 0,
26
+ };
27
+ for (const f of findings) {
28
+ if (f.severity === "critical")
29
+ s.critical++;
30
+ else if (f.severity === "high")
31
+ s.high++;
32
+ else if (f.severity === "medium")
33
+ s.medium++;
34
+ else if (f.severity === "low")
35
+ s.low++;
36
+ else
37
+ s.info++;
38
+ if (f.confidence === "proven")
39
+ s.proven++;
40
+ else if (f.confidence === "indicated")
41
+ s.indicated++;
42
+ else
43
+ s.heuristic++;
44
+ }
45
+ return s;
46
+ }
47
+ /** Sort findings: severity first, proven above indicated above heuristic. */
48
+ export function sortFindings(findings) {
49
+ const sevRank = (s) => SEVERITY_ORDER.indexOf(s);
50
+ const confRank = (c) => (c === "proven" ? 0 : c === "indicated" ? 1 : 2);
51
+ return [...findings].sort((a, b) => sevRank(a.severity) - sevRank(b.severity) || confRank(a.confidence) - confRank(b.confidence));
52
+ }
53
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/pen/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiGH,MAAM,CAAC,MAAM,cAAc,GAAkB;IAC3C,UAAU;IACV,MAAM;IACN,QAAQ;IACR,KAAK;IACL,MAAM;CACP,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,QAAsB;IACtD,MAAM,CAAC,GAAG;QACR,QAAQ,EAAE,CAAC;QACX,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,CAAC;QACT,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,CAAC;KACb,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,QAAQ,KAAK,UAAU;YAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;aACvC,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM;YAAE,CAAC,CAAC,IAAI,EAAE,CAAC;aACpC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ;YAAE,CAAC,CAAC,MAAM,EAAE,CAAC;aACxC,IAAI,CAAC,CAAC,QAAQ,KAAK,KAAK;YAAE,CAAC,CAAC,GAAG,EAAE,CAAC;;YAClC,CAAC,CAAC,IAAI,EAAE,CAAC;QACd,IAAI,CAAC,CAAC,UAAU,KAAK,QAAQ;YAAE,CAAC,CAAC,MAAM,EAAE,CAAC;aACrC,IAAI,CAAC,CAAC,UAAU,KAAK,WAAW;YAAE,CAAC,CAAC,SAAS,EAAE,CAAC;;YAChD,CAAC,CAAC,SAAS,EAAE,CAAC;IACrB,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAAC,QAAsB;IACjD,MAAM,OAAO,GAAG,CAAC,CAAc,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,CAAC,CAAgB,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CACvB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CACvG,CAAC;AACJ,CAAC"}
@@ -0,0 +1,126 @@
1
+ import type { ScanResult, Cluster } from "../analyzers/types.js";
2
+ import type { IntegrityFinding, Verdict } from "../analyzers/integrity/types.js";
3
+ export interface VerifyMetrics {
4
+ tests: {
5
+ total: number;
6
+ passed: number;
7
+ failed: number;
8
+ durationMs: number;
9
+ coverage?: number;
10
+ };
11
+ perf: {
12
+ buildTimeMs?: number;
13
+ bundleSizeBytes?: number;
14
+ };
15
+ securityCount: number;
16
+ duplicationCount: number;
17
+ }
18
+ export interface VerifyReport {
19
+ timestamp: string;
20
+ repo: string;
21
+ baselineTimestamp?: string;
22
+ risk: "High" | "Medium" | "Low";
23
+ exitCode: number;
24
+ deltas: {
25
+ passed: number;
26
+ failed: number;
27
+ durationMs: number;
28
+ coverage: number;
29
+ buildTimeMs: number;
30
+ bundleSizeBytes: number;
31
+ security: number;
32
+ duplication: number;
33
+ };
34
+ baseline: VerifyMetrics;
35
+ current: VerifyMetrics;
36
+ /** OpenPitStop score at verify time (baseline vs patched current). */
37
+ score?: {
38
+ baseline: number;
39
+ current: number;
40
+ delta: number;
41
+ grade: string;
42
+ };
43
+ /** Phase 16 integrity gate result captured by `pitstop verify`. */
44
+ integrity?: {
45
+ verdict: Verdict;
46
+ findings: IntegrityFinding[];
47
+ summary: {
48
+ confirmed: number;
49
+ suspicious: number;
50
+ total: number;
51
+ };
52
+ };
53
+ }
54
+ export interface History {
55
+ repo: string;
56
+ scans: ScanResult[];
57
+ verifies: VerifyReport[];
58
+ }
59
+ export declare function loadHistory(repo: string): History;
60
+ /**
61
+ * Gather every Phase 16 integrity verdict recorded by the loop (from verify-*.json
62
+ * and integrity-*.json in `.pitstop/`) and summarize catches vs self-corrections.
63
+ */
64
+ export declare function collectIntegrity(repo: string): ReportModel["integrity"] | undefined;
65
+ export interface MetricLine {
66
+ label: string;
67
+ value: string;
68
+ color?: "green" | "yellow" | "red" | "dim";
69
+ }
70
+ /** A committed repro test that permanently proves a fix. */
71
+ export interface ReproProof {
72
+ /** Relative path of the pitstop-repro-*.test.* file. */
73
+ file: string;
74
+ /** The finding id (from scan-latest.json) its header links back to. */
75
+ findingId?: string;
76
+ }
77
+ /** Scan the repo for committed permanent proof files. */
78
+ export declare function loadProofs(repo: string): ReproProof[];
79
+ export interface ReportModel {
80
+ repo: string;
81
+ generatedAt: string;
82
+ latestScan: ScanResult | null;
83
+ latestVerify: VerifyReport | null;
84
+ scansCount: number;
85
+ verifiesCount: number;
86
+ lines: MetricLine[];
87
+ clusters: Cluster[];
88
+ hasVerify: boolean;
89
+ /** Committed repro tests that permanently prove each fix. */
90
+ proofs: ReproProof[];
91
+ /**
92
+ * Aggregated Phase 16 integrity evidence from every `pitstop verify` (and
93
+ * `pitstop integrity`) run in `.pitstop/`. A "catch" is any non-CLEAN
94
+ * verdict; a catch followed by a later CLEAN check is a self-correction the
95
+ * loop performed on its own. Frame these as a positive — the gate working.
96
+ */
97
+ integrity?: {
98
+ checks: number;
99
+ catches: number;
100
+ selfCorrected: number;
101
+ events: {
102
+ timestamp: string;
103
+ verdict: Verdict;
104
+ findings: IntegrityFinding[];
105
+ }[];
106
+ };
107
+ }
108
+ export declare function buildModel(repo: string): ReportModel;
109
+ export declare function renderTerminal(model: ReportModel): string;
110
+ export interface MarkdownOptions {
111
+ /** Put the root-cause → symptoms clusters directly under the header. */
112
+ clustersFirst?: boolean;
113
+ /** One-line context shown under the header (branch, base, PR, etc.). */
114
+ headerNote?: string;
115
+ /** Title override (default "Repository Analysis Complete"). */
116
+ title?: string;
117
+ }
118
+ export declare function renderMarkdown(model: ReportModel, opts?: MarkdownOptions): string;
119
+ export declare function escapeHtml(s: string): string;
120
+ /** Minimal inline-SVG line chart for a metric across scans. */
121
+ export declare function svgTrend(values: (number | null)[], colorHex: string): string;
122
+ /**
123
+ * Self-contained HTML report (inline CSS, inline SVG charts, zero external
124
+ * assets) — the artifact you send to a stakeholder and it just works.
125
+ */
126
+ export declare function renderHtml(model: ReportModel): string;