@sikkuumiii/defuse 0.0.0-stage → 0.5.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 (236) hide show
  1. package/LICENSE +235 -0
  2. package/README.md +561 -2
  3. package/dist/src/cli.d.ts +20 -0
  4. package/dist/src/cli.js +619 -0
  5. package/dist/src/cli.js.map +1 -0
  6. package/dist/src/core/analyze.d.ts +178 -0
  7. package/dist/src/core/analyze.js +834 -0
  8. package/dist/src/core/analyze.js.map +1 -0
  9. package/dist/src/core/coverage.d.ts +87 -0
  10. package/dist/src/core/coverage.js +181 -0
  11. package/dist/src/core/coverage.js.map +1 -0
  12. package/dist/src/core/finding.d.ts +196 -0
  13. package/dist/src/core/finding.js +178 -0
  14. package/dist/src/core/finding.js.map +1 -0
  15. package/dist/src/core/licence.d.ts +50 -0
  16. package/dist/src/core/licence.js +56 -0
  17. package/dist/src/core/licence.js.map +1 -0
  18. package/dist/src/core/paths.d.ts +21 -0
  19. package/dist/src/core/paths.js +58 -0
  20. package/dist/src/core/paths.js.map +1 -0
  21. package/dist/src/core/score.d.ts +137 -0
  22. package/dist/src/core/score.js +232 -0
  23. package/dist/src/core/score.js.map +1 -0
  24. package/dist/src/dast/targets.d.ts +30 -0
  25. package/dist/src/dast/targets.js +79 -0
  26. package/dist/src/dast/targets.js.map +1 -0
  27. package/dist/src/dast/zap.d.ts +42 -0
  28. package/dist/src/dast/zap.js +184 -0
  29. package/dist/src/dast/zap.js.map +1 -0
  30. package/dist/src/engine/scan.d.ts +80 -0
  31. package/dist/src/engine/scan.js +129 -0
  32. package/dist/src/engine/scan.js.map +1 -0
  33. package/dist/src/engine/shapes.d.ts +47 -0
  34. package/dist/src/engine/shapes.js +328 -0
  35. package/dist/src/engine/shapes.js.map +1 -0
  36. package/dist/src/engine/walk.d.ts +60 -0
  37. package/dist/src/engine/walk.js +156 -0
  38. package/dist/src/engine/walk.js.map +1 -0
  39. package/dist/src/parse/astDump.d.ts +31 -0
  40. package/dist/src/parse/astDump.js +66 -0
  41. package/dist/src/parse/astDump.js.map +1 -0
  42. package/dist/src/parse/languages.d.ts +70 -0
  43. package/dist/src/parse/languages.js +174 -0
  44. package/dist/src/parse/languages.js.map +1 -0
  45. package/dist/src/parse/location.d.ts +17 -0
  46. package/dist/src/parse/location.js +38 -0
  47. package/dist/src/parse/location.js.map +1 -0
  48. package/dist/src/parse/node-grammars.d.ts +12 -0
  49. package/dist/src/parse/node-grammars.js +35 -0
  50. package/dist/src/parse/node-grammars.js.map +1 -0
  51. package/dist/src/parse/parser.d.ts +126 -0
  52. package/dist/src/parse/parser.js +202 -0
  53. package/dist/src/parse/parser.js.map +1 -0
  54. package/dist/src/parse/tree-store.d.ts +139 -0
  55. package/dist/src/parse/tree-store.js +236 -0
  56. package/dist/src/parse/tree-store.js.map +1 -0
  57. package/dist/src/platform/dependency-rule.d.ts +27 -0
  58. package/dist/src/platform/dependency-rule.js +21 -0
  59. package/dist/src/platform/dependency-rule.js.map +1 -0
  60. package/dist/src/platform/deps.d.ts +86 -0
  61. package/dist/src/platform/deps.js +304 -0
  62. package/dist/src/platform/deps.js.map +1 -0
  63. package/dist/src/platform/php-facts.d.ts +49 -0
  64. package/dist/src/platform/php-facts.js +67 -0
  65. package/dist/src/platform/php-facts.js.map +1 -0
  66. package/dist/src/platform/runtime-version.d.ts +78 -0
  67. package/dist/src/platform/runtime-version.js +573 -0
  68. package/dist/src/platform/runtime-version.js.map +1 -0
  69. package/dist/src/report/colors.d.ts +50 -0
  70. package/dist/src/report/colors.js +97 -0
  71. package/dist/src/report/colors.js.map +1 -0
  72. package/dist/src/report/coverage-table.d.ts +90 -0
  73. package/dist/src/report/coverage-table.js +291 -0
  74. package/dist/src/report/coverage-table.js.map +1 -0
  75. package/dist/src/report/html-report.d.ts +66 -0
  76. package/dist/src/report/html-report.js +489 -0
  77. package/dist/src/report/html-report.js.map +1 -0
  78. package/dist/src/report/human.d.ts +44 -0
  79. package/dist/src/report/human.js +575 -0
  80. package/dist/src/report/human.js.map +1 -0
  81. package/dist/src/report/json.d.ts +24 -0
  82. package/dist/src/report/json.js +178 -0
  83. package/dist/src/report/json.js.map +1 -0
  84. package/dist/src/report/mark.d.ts +17 -0
  85. package/dist/src/report/mark.js +39 -0
  86. package/dist/src/report/mark.js.map +1 -0
  87. package/dist/src/report/pricing.d.ts +33 -0
  88. package/dist/src/report/pricing.js +343 -0
  89. package/dist/src/report/pricing.js.map +1 -0
  90. package/dist/src/report/sarif.d.ts +39 -0
  91. package/dist/src/report/sarif.js +219 -0
  92. package/dist/src/report/sarif.js.map +1 -0
  93. package/dist/src/report/site.d.ts +87 -0
  94. package/dist/src/report/site.js +742 -0
  95. package/dist/src/report/site.js.map +1 -0
  96. package/dist/src/rules/code-injection.d.ts +47 -0
  97. package/dist/src/rules/code-injection.js +326 -0
  98. package/dist/src/rules/code-injection.js.map +1 -0
  99. package/dist/src/rules/command-injection.d.ts +30 -0
  100. package/dist/src/rules/command-injection.js +286 -0
  101. package/dist/src/rules/command-injection.js.map +1 -0
  102. package/dist/src/rules/contract.d.ts +198 -0
  103. package/dist/src/rules/contract.js +39 -0
  104. package/dist/src/rules/contract.js.map +1 -0
  105. package/dist/src/rules/format-string.d.ts +46 -0
  106. package/dist/src/rules/format-string.js +146 -0
  107. package/dist/src/rules/format-string.js.map +1 -0
  108. package/dist/src/rules/hardcoded-secret.d.ts +38 -0
  109. package/dist/src/rules/hardcoded-secret.js +440 -0
  110. package/dist/src/rules/hardcoded-secret.js.map +1 -0
  111. package/dist/src/rules/lib/guards.d.ts +168 -0
  112. package/dist/src/rules/lib/guards.js +1179 -0
  113. package/dist/src/rules/lib/guards.js.map +1 -0
  114. package/dist/src/rules/lib/html-safety.d.ts +75 -0
  115. package/dist/src/rules/lib/html-safety.js +755 -0
  116. package/dist/src/rules/lib/html-safety.js.map +1 -0
  117. package/dist/src/rules/lib/local-build.d.ts +59 -0
  118. package/dist/src/rules/lib/local-build.js +320 -0
  119. package/dist/src/rules/lib/local-build.js.map +1 -0
  120. package/dist/src/rules/lib/strings.d.ts +208 -0
  121. package/dist/src/rules/lib/strings.js +1970 -0
  122. package/dist/src/rules/lib/strings.js.map +1 -0
  123. package/dist/src/rules/path-traversal.d.ts +33 -0
  124. package/dist/src/rules/path-traversal.js +96 -0
  125. package/dist/src/rules/path-traversal.js.map +1 -0
  126. package/dist/src/rules/registry.d.ts +19 -0
  127. package/dist/src/rules/registry.js +77 -0
  128. package/dist/src/rules/registry.js.map +1 -0
  129. package/dist/src/rules/sql-injection.d.ts +36 -0
  130. package/dist/src/rules/sql-injection.js +299 -0
  131. package/dist/src/rules/sql-injection.js.map +1 -0
  132. package/dist/src/rules/ssrf.d.ts +39 -0
  133. package/dist/src/rules/ssrf.js +111 -0
  134. package/dist/src/rules/ssrf.js.map +1 -0
  135. package/dist/src/rules/unbounded-copy.d.ts +37 -0
  136. package/dist/src/rules/unbounded-copy.js +147 -0
  137. package/dist/src/rules/unbounded-copy.js.map +1 -0
  138. package/dist/src/rules/unsafe-deserialization.d.ts +43 -0
  139. package/dist/src/rules/unsafe-deserialization.js +276 -0
  140. package/dist/src/rules/unsafe-deserialization.js.map +1 -0
  141. package/dist/src/rules/weak-hash.d.ts +37 -0
  142. package/dist/src/rules/weak-hash.js +197 -0
  143. package/dist/src/rules/weak-hash.js.map +1 -0
  144. package/dist/src/rules/xss.d.ts +38 -0
  145. package/dist/src/rules/xss.js +527 -0
  146. package/dist/src/rules/xss.js.map +1 -0
  147. package/dist/src/taint/content-type.d.ts +19 -0
  148. package/dist/src/taint/content-type.js +20 -0
  149. package/dist/src/taint/content-type.js.map +1 -0
  150. package/dist/src/taint/dictionaries.d.ts +23 -0
  151. package/dist/src/taint/dictionaries.js +1778 -0
  152. package/dist/src/taint/dictionaries.js.map +1 -0
  153. package/dist/src/taint/fold.d.ts +59 -0
  154. package/dist/src/taint/fold.js +1177 -0
  155. package/dist/src/taint/fold.js.map +1 -0
  156. package/dist/src/taint/java-scope.d.ts +61 -0
  157. package/dist/src/taint/java-scope.js +212 -0
  158. package/dist/src/taint/java-scope.js.map +1 -0
  159. package/dist/src/taint/local-map.d.ts +79 -0
  160. package/dist/src/taint/local-map.js +603 -0
  161. package/dist/src/taint/local-map.js.map +1 -0
  162. package/dist/src/taint/project.d.ts +172 -0
  163. package/dist/src/taint/project.js +617 -0
  164. package/dist/src/taint/project.js.map +1 -0
  165. package/dist/src/taint/tracer.d.ts +265 -0
  166. package/dist/src/taint/tracer.js +3817 -0
  167. package/dist/src/taint/tracer.js.map +1 -0
  168. package/dist/src/taint/types.d.ts +484 -0
  169. package/dist/src/taint/types.js +47 -0
  170. package/dist/src/taint/types.js.map +1 -0
  171. package/dist/src/taint/visibility.d.ts +25 -0
  172. package/dist/src/taint/visibility.js +96 -0
  173. package/dist/src/taint/visibility.js.map +1 -0
  174. package/docs/examples/defuse.json +20 -0
  175. package/docs/examples/dvwa-urls.json +14 -0
  176. package/docs/examples/github-code-scanning.yml +54 -0
  177. package/docs/examples/tiny.js +4 -0
  178. package/package.json +73 -4
  179. package/src/cli.ts +747 -0
  180. package/src/core/analyze.ts +1072 -0
  181. package/src/core/coverage.ts +269 -0
  182. package/src/core/finding.ts +311 -0
  183. package/src/core/licence.ts +61 -0
  184. package/src/core/paths.ts +59 -0
  185. package/src/core/score.ts +353 -0
  186. package/src/dast/targets.ts +121 -0
  187. package/src/dast/zap.ts +246 -0
  188. package/src/engine/scan.ts +200 -0
  189. package/src/engine/shapes.ts +348 -0
  190. package/src/engine/walk.ts +196 -0
  191. package/src/parse/astDump.ts +85 -0
  192. package/src/parse/languages.ts +232 -0
  193. package/src/parse/location.ts +44 -0
  194. package/src/parse/node-grammars.ts +41 -0
  195. package/src/parse/parser.ts +262 -0
  196. package/src/parse/tree-store.ts +301 -0
  197. package/src/platform/dependency-rule.ts +33 -0
  198. package/src/platform/deps.ts +374 -0
  199. package/src/platform/php-facts.ts +85 -0
  200. package/src/platform/runtime-version.ts +710 -0
  201. package/src/report/colors.ts +107 -0
  202. package/src/report/coverage-table.ts +359 -0
  203. package/src/report/html-report.ts +601 -0
  204. package/src/report/human.ts +811 -0
  205. package/src/report/json.ts +189 -0
  206. package/src/report/mark.ts +47 -0
  207. package/src/report/pricing.ts +374 -0
  208. package/src/report/sarif.ts +235 -0
  209. package/src/report/site.ts +760 -0
  210. package/src/rules/code-injection.ts +346 -0
  211. package/src/rules/command-injection.ts +296 -0
  212. package/src/rules/contract.ts +220 -0
  213. package/src/rules/format-string.ts +158 -0
  214. package/src/rules/hardcoded-secret.ts +485 -0
  215. package/src/rules/lib/guards.ts +1235 -0
  216. package/src/rules/lib/html-safety.ts +793 -0
  217. package/src/rules/lib/local-build.ts +329 -0
  218. package/src/rules/lib/strings.ts +2034 -0
  219. package/src/rules/path-traversal.ts +101 -0
  220. package/src/rules/registry.ts +90 -0
  221. package/src/rules/sql-injection.ts +311 -0
  222. package/src/rules/ssrf.ts +118 -0
  223. package/src/rules/unbounded-copy.ts +162 -0
  224. package/src/rules/unsafe-deserialization.ts +291 -0
  225. package/src/rules/weak-hash.ts +226 -0
  226. package/src/rules/xss.ts +572 -0
  227. package/src/taint/content-type.ts +20 -0
  228. package/src/taint/dictionaries.ts +1855 -0
  229. package/src/taint/fold.ts +1206 -0
  230. package/src/taint/java-scope.ts +200 -0
  231. package/src/taint/local-map.ts +594 -0
  232. package/src/taint/project.ts +774 -0
  233. package/src/taint/tracer.ts +4298 -0
  234. package/src/taint/types.ts +511 -0
  235. package/src/taint/visibility.ts +100 -0
  236. package/tsconfig.json +61 -0
@@ -0,0 +1,24 @@
1
+ /**
2
+ * MACHINE-READABLE REPORT
3
+ *
4
+ * Two rules for this format:
5
+ *
6
+ * 1. It is a SUPERSET of the human report. Anything the terminal shows must be
7
+ * in here, including the gaps and the suppressions. A JSON consumer must not
8
+ * be able to build a rosier picture than a human reading the same scan.
9
+ *
10
+ * 2. `confidence` is a top-level field on every finding, and the `honesty`
11
+ * block at the document root explains what the values mean. A dashboard that
12
+ * ingests this cannot accidentally present unverified matches as confirmed
13
+ * vulnerabilities without deliberately discarding the field.
14
+ *
15
+ * RELATIONSHIP TO SARIF: this shape deliberately resembles SARIF (the OASIS
16
+ * standard GitHub code scanning consumes) without pretending to be it, because
17
+ * emitting invalid SARIF and calling it SARIF would be its own small lie. Real
18
+ * SARIF now exists behind `--sarif` (report/sarif.ts), typed against the
19
+ * official 2.1.0 definitions so the compiler rejects a malformed document.
20
+ * This format stays because it carries things SARIF has no room for - the
21
+ * coverage matrix, verified-clean lines, trace limits and the score gauges.
22
+ */
23
+ import type { ScanResult } from '../engine/scan.js';
24
+ export declare function renderJson(result: ScanResult, pretty?: boolean): string;
@@ -0,0 +1,178 @@
1
+ /**
2
+ * MACHINE-READABLE REPORT
3
+ *
4
+ * Two rules for this format:
5
+ *
6
+ * 1. It is a SUPERSET of the human report. Anything the terminal shows must be
7
+ * in here, including the gaps and the suppressions. A JSON consumer must not
8
+ * be able to build a rosier picture than a human reading the same scan.
9
+ *
10
+ * 2. `confidence` is a top-level field on every finding, and the `honesty`
11
+ * block at the document root explains what the values mean. A dashboard that
12
+ * ingests this cannot accidentally present unverified matches as confirmed
13
+ * vulnerabilities without deliberately discarding the field.
14
+ *
15
+ * RELATIONSHIP TO SARIF: this shape deliberately resembles SARIF (the OASIS
16
+ * standard GitHub code scanning consumes) without pretending to be it, because
17
+ * emitting invalid SARIF and calling it SARIF would be its own small lie. Real
18
+ * SARIF now exists behind `--sarif` (report/sarif.ts), typed against the
19
+ * official 2.1.0 definitions so the compiler rejects a malformed document.
20
+ * This format stays because it carries things SARIF has no room for - the
21
+ * coverage matrix, verified-clean lines, trace limits and the score gauges.
22
+ */
23
+ import { LICENCE_SPDX } from '../core/licence.js';
24
+ export function renderJson(result, pretty = true) {
25
+ const bySeverity = {};
26
+ for (const finding of result.findings) {
27
+ bySeverity[finding.severity] = (bySeverity[finding.severity] ?? 0) + 1;
28
+ }
29
+ const document = {
30
+ tool: {
31
+ name: 'Defuse',
32
+ version: result.coverage.engine.version,
33
+ analysis: result.coverage.engine.analysisLabel,
34
+ // Taken from the capability block rather than retyped here. This list was
35
+ // hand-written once and went stale immediately - it still claimed the
36
+ // tracer worked "within one function (JS/TS/Python)" long after it
37
+ // followed values across files in every language. A machine-readable
38
+ // report that overstates OR understates the engine is the same bug.
39
+ analysisTypes: result.coverage.engine.implemented,
40
+ // Machine-readable, because a consumer feeding this into a compliance
41
+ // pipeline should not have to read a README to learn the terms.
42
+ license: LICENCE_SPDX,
43
+ },
44
+ target: result.target,
45
+ scannedAt: new Date().toISOString(),
46
+ // Placed BEFORE findings on purpose: a consumer reading top-to-bottom meets
47
+ // the caveats before the results.
48
+ honesty: {
49
+ signatureBasedFindings: result.findings.filter((f) => f.confidence === 'signature-based')
50
+ .length,
51
+ flowVerifiedFindings: result.findings.filter((f) => f.confidence === 'flow-verified').length,
52
+ signatureGuessesSupersededByProof: result.stats.signaturesUpgraded,
53
+ signatureGuessesWithdrawnAsSanitised: result.stats.signaturesRetracted,
54
+ /*
55
+ * Withdrawn because every value spliced in is provably a fixed literal on
56
+ * every path that runs - a branch that cannot run, a condition decided at
57
+ * compile time, a same-file helper that only ever returns a literal. Each
58
+ * one is listed under diagnostics.verifiedClean with kind "constant" and
59
+ * the reason, so the reasoning can be checked line by line.
60
+ */
61
+ signatureGuessesWithdrawnAsConstant: result.stats.signaturesProvedConstant,
62
+ /*
63
+ * Branches and cases the tracer did not follow because a condition fixed
64
+ * at compile time means they cannot run. A flow that lived only inside one
65
+ * of them is not reported - so each is listed under
66
+ * diagnostics.unreachableCodeSkipped, with the decision, rather than
67
+ * leaving a missing finding with no explanation.
68
+ */
69
+ regionsProvedUnreachable: result.stats.regionsProvedUnreachable,
70
+ /*
71
+ * Reads from a local map or list answered by the key or the position,
72
+ * because every write the collection could receive is visible (see
73
+ * taint/local-map.ts) - each listed under diagnostics.collectionReadsResolved
74
+ * with the write that answers it.
75
+ */
76
+ collectionReadsResolved: result.stats.collectionReadsResolved,
77
+ /*
78
+ * Calls where a trace ENDED because the function returns new data - a
79
+ * database row, a file's contents - not its argument. Not a claim of
80
+ * safety: nothing is cleared by a stop, and a sink further on is still
81
+ * reported by its signature rule. Each is listed under
82
+ * diagnostics.tracesStoppedAtNewData with what the call returns instead.
83
+ */
84
+ tracesStoppedAtNewData: result.stats.tracesStoppedAtNewData,
85
+ meaningOfConfidence: result.coverage.engine.meaningOfConfidence,
86
+ notImplemented: result.coverage.engine.notImplemented,
87
+ dataFlowCoverageByLanguage: result.coverage.taint,
88
+ crossFileResolution: result.crossFile,
89
+ warning: 'Findings labelled signature-based are UNVERIFIED pattern matches - the data flow was ' +
90
+ 'not traced and they may be false positives. Findings labelled flow-verified carry a ' +
91
+ 'complete source-to-sink path in `flowPath`; check it rather than trusting the label. ' +
92
+ 'Neither label proves exploitability in a running system.',
93
+ },
94
+ summary: {
95
+ total: result.findings.length,
96
+ bySeverity,
97
+ byConfidence: {
98
+ 'signature-based': result.findings.filter((f) => f.confidence === 'signature-based').length,
99
+ 'flow-verified': result.findings.filter((f) => f.confidence === 'flow-verified').length,
100
+ },
101
+ suppressed: result.suppressions.length,
102
+ },
103
+ findings: result.findings.map((finding) => ({
104
+ ruleId: finding.ruleId,
105
+ ruleName: finding.ruleName,
106
+ severity: finding.severity,
107
+ confidence: finding.confidence,
108
+ verified: finding.verified,
109
+ flowPath: finding.flowPath,
110
+ cwe: finding.cwe,
111
+ owasp: finding.owasp,
112
+ message: finding.message,
113
+ reasoning: finding.reasoning,
114
+ limitations: finding.limitations,
115
+ location: finding.location,
116
+ detectedAt: finding.detectedAt,
117
+ })),
118
+ coverage: {
119
+ counts: result.coverage.counts,
120
+ gaps: result.coverage.gaps,
121
+ matrix: result.coverage.matrix,
122
+ fileTypesPresentButNotScanned: result.coverage.unscannedExtensions,
123
+ },
124
+ diagnostics: {
125
+ stats: result.stats,
126
+ filesByLanguage: result.byLanguage,
127
+ parseProblems: result.parseProblems,
128
+ suppressions: result.suppressions,
129
+ /*
130
+ * Every line proved clean, each with `reason` - what cleaned it and on
131
+ * which line - and, when there were any, `assumes`: functions Defuse
132
+ * does not model that the value went through AFTER it was cleaned, each
133
+ * taken to hand back what it was given. A tool reading this file can
134
+ * hold the receipts that rest on trust to a different standard.
135
+ */
136
+ verifiedClean: result.verifiedClean,
137
+ unreachableCodeSkipped: result.unreachableCode,
138
+ collectionReadsResolved: result.collectionReadsResolved,
139
+ tracesStoppedAtNewData: result.tracesStoppedAtNewData,
140
+ /*
141
+ * Which PHP the project declares (Dockerfile, compose, composer.json,
142
+ * .php-version) and what php.net's facts say about each - with the date
143
+ * those facts were checked, and notes for what could not be checked.
144
+ * Null when --only left the check out.
145
+ */
146
+ runtimeVersions: result.runtimeVersions
147
+ ? {
148
+ factsChecked: result.runtimeVersions.factsChecked,
149
+ declared: result.runtimeVersions.declared,
150
+ notes: result.runtimeVersions.notes,
151
+ }
152
+ : null,
153
+ /** What `--deps` read and asked osv.dev; null when it did not run. */
154
+ dependencies: result.dependencies ?? null,
155
+ oversizedFilesSkipped: result.oversizedFiles,
156
+ excludedByUser: result.excluded,
157
+ /**
158
+ * What the scan spent on syntax trees.
159
+ *
160
+ * `reparses` above zero means the project did not fit in the tree budget
161
+ * and files were parsed more than once. The findings are unaffected - a
162
+ * re-parse of the same bytes with the same grammar is the same tree - but
163
+ * the scan took longer than it needed to, and saying so is the difference
164
+ * between a user tuning the budget and a user assuming the tool is slow.
165
+ */
166
+ treeMemory: {
167
+ ...result.treeMemory,
168
+ note: result.treeMemory.reparses === 0
169
+ ? 'Every file was parsed exactly once; the project fitted in the tree budget.'
170
+ : `The project did not fit in the tree budget, so ${result.treeMemory.reparses} ` +
171
+ 'file(s) were parsed more than once. Answers are unchanged; the scan was slower. ' +
172
+ 'Raise DEFUSE_TREE_BUDGET_MB to trade memory back for speed.',
173
+ },
174
+ },
175
+ };
176
+ return JSON.stringify(document, null, pretty ? 2 : 0);
177
+ }
178
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/report/json.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * THE MARK, AS A VECTOR.
3
+ *
4
+ * docs/defuse-mark.png is the source of truth for the mark, and it is not in
5
+ * the npm package - so a report written by an installed copy of the CLI could
6
+ * not include it. This is the same shape traced to a path (potrace, from the PNG
7
+ * at 4x), small enough to inline, so a report file carries its own mark and
8
+ * loads nothing from anywhere.
9
+ */
10
+ /** #792CF7 - the mark's own colour, sampled from the PNG. */
11
+ export declare const MARK_COLOUR = "#792CF7";
12
+ /** An inline <svg> of the mark, `width` pixels wide; height follows the 262:240 shape. */
13
+ export declare function markSvg(width: number, title?: string): string;
14
+ /** Columns the banner needs. */
15
+ export declare const BANNER_WIDTH: number;
16
+ /** The banner as plain lines. */
17
+ export declare function bannerLines(): string[];
@@ -0,0 +1,39 @@
1
+ /**
2
+ * THE MARK, AS A VECTOR.
3
+ *
4
+ * docs/defuse-mark.png is the source of truth for the mark, and it is not in
5
+ * the npm package - so a report written by an installed copy of the CLI could
6
+ * not include it. This is the same shape traced to a path (potrace, from the PNG
7
+ * at 4x), small enough to inline, so a report file carries its own mark and
8
+ * loads nothing from anywhere.
9
+ */
10
+ /** #792CF7 - the mark's own colour, sampled from the PNG. */
11
+ export const MARK_COLOUR = '#792CF7';
12
+ const MARK_PATH = 'M162 9580 c-7 -11 -18 -20 -26 -20 -17 0 -96 -78 -96 -95 0 -6 -9 -20 -20 -30 -20 -18 -20 -31 -20 -2350 0 -2009 2 -2334 14 -2338 8 -3 22 -22 31 -41 22 -47 83 -94 142 -112 40 -12 240 -14 1227 -14 1123 1 1181 0 1187 -17 12 -29 10 -1733 -1 -1754 -10 -18 -51 -18 -1203 -19 l-1192 0 -55 -28 c-37 -18 -66 -42 -87 -72 -18 -25 -39 -53 -48 -62 -13 -16 -15 -154 -15 -1231 0 -1201 0 -1214 20 -1232 11 -10 20 -22 20 -27 0 -20 48 -72 88 -95 23 -14 42 -29 42 -34 0 -5 501 -9 1225 -9 l1224 0 25 23 c14 12 41 35 61 51 20 16 47 51 61 77 l24 48 0 1018 c0 560 4 1024 8 1031 7 10 249 12 1208 13 l1199 0 5 -1028 c5 -1108 3 -1061 58 -1128 14 -16 41 -41 61 -55 20 -14 40 -31 44 -37 13 -20 702 -18 749 2 19 7 84 19 144 25 172 16 341 48 589 111 186 48 206 54 515 164 25 8 54 20 65 25 11 5 72 31 135 59 134 59 386 186 478 241 17 11 47 29 65 40 17 11 48 29 67 40 59 35 154 98 271 182 163 115 355 277 559 468 283 266 641 727 833 1073 9 18 35 64 57 102 59 104 220 441 220 460 0 4 8 26 19 49 21 48 28 65 91 251 60 180 90 277 90 293 0 8 8 44 19 80 43 153 83 375 102 567 6 61 17 125 25 144 20 49 20 757 0 816 -8 22 -19 92 -25 155 -26 275 -107 634 -210 935 -67 197 -79 229 -95 260 -9 17 -16 34 -16 39 0 5 -9 30 -21 55 -12 25 -29 64 -39 86 -41 90 -123 254 -160 320 -22 39 -48 84 -57 102 -66 118 -166 273 -293 451 -220 311 -578 681 -920 952 -162 129 -178 140 -340 247 -63 42 -127 84 -142 94 -15 11 -30 19 -34 19 -4 0 -15 6 -23 14 -52 45 -492 262 -676 333 -22 8 -55 21 -72 29 -29 12 -228 79 -353 118 -25 8 -94 26 -155 40 -60 15 -137 33 -170 42 -91 22 -279 52 -406 65 -63 6 -129 17 -148 25 -28 12 -472 14 -2985 14 -2940 0 -2951 0 -2964 -20z m5648 -2648 c153 -13 203 -20 340 -51 111 -25 188 -48 227 -66 17 -8 35 -15 40 -15 47 0 389 -183 494 -265 15 -11 39 -29 55 -40 114 -80 352 -322 434 -441 36 -52 108 -162 127 -194 42 -70 153 -303 153 -323 1 -6 9 -30 20 -52 11 -22 19 -46 20 -54 0 -8 9 -44 20 -80 98 -330 97 -754 -2 -1111 -113 -409 -365 -796 -693 -1068 -44 -37 -82 -69 -85 -72 -3 -3 -16 -13 -30 -22 -14 -10 -44 -31 -67 -47 -163 -116 -433 -240 -628 -290 -235 -60 -306 -68 -645 -73 l-185 -3 -5 1095 -5 1095 -27 52 c-33 61 -103 122 -155 134 -21 5 -572 9 -1225 9 l-1188 0 -5 23 c-3 12 -4 435 -3 940 3 803 5 919 18 927 23 14 2817 7 3000 -8z';
13
+ /** An inline <svg> of the mark, `width` pixels wide; height follows the 262:240 shape. */
14
+ export function markSvg(width, title = '') {
15
+ const height = Math.round(((width * 240) / 262) * 100) / 100;
16
+ const label = title ? ` role="img" aria-label="${title}"` : ' aria-hidden="true"';
17
+ return (`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1048.12 960.13" width="${width}" height="${height}"${label}>` +
18
+ `<g transform="translate(0,960) scale(0.1,-0.1)" fill="${MARK_COLOUR}"><path d="${MARK_PATH}"/></g></svg>`);
19
+ }
20
+ /*
21
+ * THE MARK, AS BLOCKS - the terminal banner.
22
+ *
23
+ * "DEFUSE" in chunky block letters with a box-drawing shadow.
24
+ */
25
+ const BANNER = [
26
+ '██████╗ ███████╗███████╗██╗ ██╗███████╗███████╗',
27
+ '██╔══██╗██╔════╝██╔════╝██║ ██║██╔════╝██╔════╝',
28
+ '██║ ██║█████╗ █████╗ ██║ ██║███████╗█████╗',
29
+ '██║ ██║██╔══╝ ██╔══╝ ██║ ██║╚════██║██╔══╝',
30
+ '██████╔╝███████╗██║ ╚██████╔╝███████║███████╗',
31
+ '╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚══════╝╚══════╝',
32
+ ];
33
+ /** Columns the banner needs. */
34
+ export const BANNER_WIDTH = Math.max(...BANNER.map((l) => l.length));
35
+ /** The banner as plain lines. */
36
+ export function bannerLines() {
37
+ return [...BANNER];
38
+ }
39
+ //# sourceMappingURL=mark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mark.js","sourceRoot":"","sources":["../../../src/report/mark.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,6DAA6D;AAC7D,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAErC,MAAM,SAAS,GACb,wpEAAwpE,CAAC;AAE3pE,0FAA0F;AAC1F,MAAM,UAAU,OAAO,CAAC,KAAa,EAAE,KAAK,GAAG,EAAE;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;IAC7D,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,2BAA2B,KAAK,GAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC;IAClF,OAAO,CACL,+EAA+E,KAAK,aAAa,MAAM,IAAI,KAAK,GAAG;QACnH,yDAAyD,WAAW,cAAc,SAAS,eAAe,CAC3G,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,MAAM,GAAG;IACb,mDAAmD;IACnD,mDAAmD;IACnD,iDAAiD;IACjD,iDAAiD;IACjD,mDAAmD;IACnD,mDAAmD;CACpD,CAAC;AAEF,gCAAgC;AAChC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAErE,iCAAiC;AACjC,MAAM,UAAU,WAAW;IACzB,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { BenchmarkResult } from './coverage-table.js';
2
+ export interface PlanFeature {
3
+ readonly name: string;
4
+ readonly detail: string;
5
+ }
6
+ export interface Plan {
7
+ readonly name: string;
8
+ readonly status: 'available' | 'coming-soon';
9
+ /** Shown only for an available plan. */
10
+ readonly price?: {
11
+ readonly amount: string;
12
+ readonly unit: string;
13
+ readonly note?: string;
14
+ };
15
+ readonly forWhom: string;
16
+ /**
17
+ * A fact about the plan, shown in the corner of its card. A fact, never a
18
+ * ranking: "open source", "from 5 developers". See the note above on badges.
19
+ */
20
+ readonly badge?: string;
21
+ /** "Everything in Pro, and:" - the plan below this one. */
22
+ readonly builds?: string;
23
+ readonly features: readonly PlanFeature[];
24
+ readonly cta: {
25
+ readonly label: string;
26
+ readonly href: string;
27
+ readonly primary?: boolean;
28
+ };
29
+ }
30
+ /** Team is priced per developer with a floor of this many. */
31
+ export declare const TEAM_MIN_SEATS = 5;
32
+ export declare function plans(): Plan[];
33
+ export declare function renderPricing(benchmark: BenchmarkResult): string;