@secureport/core 2.2.0 → 2.3.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.
@@ -60,8 +60,11 @@ function describeRetest(snapshot) {
60
60
  * an issue left open because the run never covered it looks identical to one
61
61
  * left open because the run found it again, and telling a reader those are the
62
62
  * same thing is the failure this report exists to avoid.
63
+ *
64
+ * Exported: it is per-issue and needs nothing but the one entry, which is
65
+ * exactly what the streaming machine renderers can offer it a row at a time.
63
66
  */
64
- function verdictFor(entry) {
67
+ export function verdictFor(entry) {
65
68
  if (entry.change === 'resolved')
66
69
  return 'fixed';
67
70
  if (entry.change === 'regressed')
@@ -70,8 +73,16 @@ function verdictFor(entry) {
70
73
  return 'new';
71
74
  return entry.findings.length > 0 ? 'still_present' : 'not_retested';
72
75
  }
73
- /** Works out what a report cannot establish, from the run rather than a template. */
74
- function describeLimitations(snapshot, basis, omitted) {
76
+ /**
77
+ * Works out what a report cannot establish, from the run rather than a
78
+ * template.
79
+ *
80
+ * Takes primitives rather than a {@link Snapshot} so the streaming machine
81
+ * renderers can produce the same wording from a fold over a cursor, without
82
+ * needing the eagerly-materialised issue array this package's PDF/HTML path
83
+ * builds.
84
+ */
85
+ export function describeLimitations(coveragePaths, runCreatedAt, basis, suppressedCount, omitted) {
75
86
  const limitations = [];
76
87
  if (!basis.includesManual) {
77
88
  limitations.push('This is evidence of automated security testing. It is not a human-led penetration ' +
@@ -79,15 +90,15 @@ function describeLimitations(snapshot, basis, omitted) {
79
90
  }
80
91
  limitations.push('Findings should be verified by a qualified technician before this document is relied ' +
81
92
  'upon as audit evidence.');
82
- limitations.push(`Testing covered only ${snapshot.run.coverage.paths.join(', ')}. Anything outside that ` +
93
+ limitations.push(`Testing covered only ${coveragePaths.join(', ')}. Anything outside that ` +
83
94
  'was not examined, and its absence from this document is not evidence that it is sound.');
84
- limitations.push(`This reflects the state of the target as of ${snapshot.run.createdAt
95
+ limitations.push(`This reflects the state of the target as of ${runCreatedAt
85
96
  .toISOString()
86
97
  .slice(0, 10)}. It says nothing about the target before or after that date.`);
87
98
  limitations.push('Automated testing cannot establish the absence of a vulnerability. A clean result means ' +
88
99
  'nothing was detected, not that nothing is there.');
89
- if (snapshot.suppressed.length > 0) {
90
- limitations.push(`${snapshot.suppressed.length} finding${snapshot.suppressed.length === 1 ? ' has' : 's have'} been ` +
100
+ if (suppressedCount > 0) {
101
+ limitations.push(`${suppressedCount} finding${suppressedCount === 1 ? ' has' : 's have'} been ` +
91
102
  'suppressed and excluded from the counts above. They are listed in full in the appendix.');
92
103
  }
93
104
  // Immediately after the suppression sentence and before the compliance one,
@@ -104,18 +115,75 @@ function describeLimitations(snapshot, basis, omitted) {
104
115
  * refusal rather than a sanitisation.
105
116
  */
106
117
  const HEX_COLOUR = /^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/iu;
107
- const DEFAULT_TITLES = Object.freeze({
118
+ /**
119
+ * Why this branding cannot be rendered, or `undefined` if it can.
120
+ *
121
+ * **Exported so the rules have one home rather than two.** {@link buildReportModel}
122
+ * enforces these at render time, which is the last possible moment — by then the
123
+ * value has been stored, and the caller who set it is long gone. A hosted
124
+ * service wants to refuse it at the boundary instead, with a `400` naming the
125
+ * field. That needs the same two rules in two places, and a colour pattern
126
+ * copied into an API schema is a copy free to drift from the one that actually
127
+ * protects the stylesheet.
128
+ *
129
+ * So both callers ask this. The messages are identical wherever the value is
130
+ * rejected, because there is only one place that composes them.
131
+ *
132
+ * The white-label rule is deliberately **not** here: it depends on the report
133
+ * kind and on `preparedBy`, so it is a property of the options rather than of
134
+ * the branding, and only the renderer can decide it.
135
+ */
136
+ export function brandingProblem(branding) {
137
+ const colour = branding?.primaryColour;
138
+ if (colour !== undefined && !HEX_COLOUR.test(colour)) {
139
+ return (`primaryColour must be a hex triplet such as #0a7 or #00aa77, not ${JSON.stringify(colour)}: ` +
140
+ 'it is interpolated into the document stylesheet, where anything else could end the element');
141
+ }
142
+ const logo = branding?.logo;
143
+ if (logo !== undefined && !logo.startsWith('data:image/')) {
144
+ return (`logo must be a data: URI, not ${JSON.stringify(logo.slice(0, 40))}: ` +
145
+ 'a linked image would make the report depend on a network at render time, ' +
146
+ 'which is the guarantee that lets it be rendered to PDF reproducibly');
147
+ }
148
+ return undefined;
149
+ }
150
+ /**
151
+ * Who the document says carried out the testing, resolved once so the PDF/HTML
152
+ * path and the streaming machine path cannot word it two different ways.
153
+ *
154
+ * @throws TypeError A white-labelled attestation naming nobody: a formal
155
+ * statement that testing was carried out has to say who carried it out.
156
+ */
157
+ export function resolveAttestor(options) {
158
+ const attestor = options.preparedBy ?? options.branding?.companyName;
159
+ // An attestation is a statement that a named party carried out testing. With
160
+ // Secureport's name removed and nothing put in its place there is no such
161
+ // party, and the document would assert something on nobody's behalf.
162
+ if (attestor === undefined &&
163
+ options.branding?.whiteLabel === true &&
164
+ options.kind === 'attest') {
165
+ throw new TypeError('a white-labelled attestation must name who carried out the testing: ' +
166
+ 'set branding.companyName or preparedBy');
167
+ }
168
+ return attestor ?? 'Secureport';
169
+ }
170
+ /** The title printed when {@link ReportOptions.title} is not given. */
171
+ export const DEFAULT_TITLES = Object.freeze({
108
172
  pen: 'Penetration Test Report',
109
173
  vap: 'Vulnerability Assessment Report',
110
174
  exec: 'Executive Summary',
111
175
  attest: 'Attestation of Security Testing',
112
176
  retest: 'Retest Report',
113
177
  });
114
- /** Works out how the findings were produced, from the run rather than a claim. */
115
- function describeBasis(snapshot) {
116
- const kind = snapshot.run.kind;
117
- const engines = snapshot.run.engines;
118
- const includesManual = snapshot.issues.some((i) => i.issue.origin === 'manual');
178
+ /**
179
+ * Works out how the findings were produced, from the run rather than a claim.
180
+ *
181
+ * Takes `kind`/`engines`/`includesManual` as primitives, the same reason
182
+ * {@link describeLimitations} does: the streaming machine renderers know
183
+ * `includesManual` only once a fold over the issue cursor finishes, and have
184
+ * no `Snapshot` to read `run.kind`/`run.engines` from.
185
+ */
186
+ export function describeBasis(kind, engines, includesManual) {
119
187
  const automated = kind === 'scan';
120
188
  const uploaded = kind === 'upload';
121
189
  const parts = [];
@@ -222,7 +290,7 @@ export function buildReportModel(snapshot, options) {
222
290
  `${omittedBelowFloor === 1 ? 'is' : 'are'} included in every count above.`,
223
291
  };
224
292
  const outstandingTotal = SEVERITY_ORDER.reduce((sum, s) => sum + outstanding[s], 0);
225
- const basis = describeBasis(snapshot);
293
+ const basis = describeBasis(snapshot.run.kind, snapshot.run.engines, snapshot.issues.some((i) => i.issue.origin === 'manual'));
226
294
  const retest = describeRetest(snapshot);
227
295
  // Rendering a retest of nothing is the over-claim §7 warns about: the
228
296
  // document's whole content is a comparison, and one run does not have one.
@@ -230,25 +298,10 @@ export function buildReportModel(snapshot, options) {
230
298
  throw new TypeError('a retest report needs a baseline: build the snapshot with `previous` set to the run being retested');
231
299
  }
232
300
  const branding = options.branding;
233
- const colour = branding?.primaryColour;
234
- if (colour !== undefined && !HEX_COLOUR.test(colour)) {
235
- throw new TypeError(`primaryColour must be a hex triplet such as #0a7 or #00aa77, not ${JSON.stringify(colour)}: ` +
236
- 'it is interpolated into the document stylesheet, where anything else could end the element');
237
- }
238
- const logo = branding?.logo;
239
- if (logo !== undefined && !logo.startsWith('data:image/')) {
240
- throw new TypeError(`logo must be a data: URI, not ${JSON.stringify(logo.slice(0, 40))}: ` +
241
- 'a linked image would make the report depend on a network at render time, ' +
242
- 'which is the guarantee that lets it be rendered to PDF reproducibly');
243
- }
244
- const attestor = options.preparedBy ?? branding?.companyName;
245
- // An attestation is a statement that a named party carried out testing. With
246
- // Secureport's name removed and nothing put in its place there is no such
247
- // party, and the document would assert something on nobody's behalf.
248
- if (attestor === undefined && branding?.whiteLabel === true && options.kind === 'attest') {
249
- throw new TypeError('a white-labelled attestation must name who carried out the testing: ' +
250
- 'set branding.companyName or preparedBy');
251
- }
301
+ const problem = brandingProblem(branding);
302
+ if (problem !== undefined)
303
+ throw new TypeError(problem);
304
+ const attestor = resolveAttestor(options);
252
305
  return {
253
306
  kind: options.kind,
254
307
  title: options.title ?? DEFAULT_TITLES[options.kind],
@@ -256,13 +309,13 @@ export function buildReportModel(snapshot, options) {
256
309
  generatedAt: options.now,
257
310
  ...(options.preparedBy === undefined ? {} : { preparedBy: options.preparedBy }),
258
311
  ...(options.preparedFor === undefined ? {} : { preparedFor: options.preparedFor }),
259
- attestor: attestor ?? 'Secureport',
312
+ attestor,
260
313
  coverPage: options.coverPage === true,
261
314
  tableOfContents: options.tableOfContents === true,
262
315
  ...(branding === undefined ? {} : { branding }),
263
316
  basis,
264
317
  evidenceVerbosity: options.evidenceVerbosity ?? 'summary',
265
- limitations: describeLimitations(snapshot, basis, omitted),
318
+ limitations: describeLimitations(snapshot.run.coverage.paths, snapshot.run.createdAt, basis, snapshot.suppressed.length, omitted),
266
319
  sections,
267
320
  resolved: options.includeResolved === false ? [] : resolved,
268
321
  ...(omitted === undefined ? {} : { omitted }),
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/report/model.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAgbhD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,cAAc,GAA4C,MAAM,CAAC,MAAM,CAAC;IACnF,KAAK,EAAE,OAAO;IACd,aAAa,EAAE,eAAe;IAC9B,QAAQ,EAAE,UAAU;IACpB,YAAY,EAAE,cAAc;IAC5B,GAAG,EAAE,WAAW;CACjB,CAAC,CAAC;AAuCH,yEAAyE;AACzE,SAAS,cAAc,CAAC,QAAkB;IACxC,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC;IAC9B,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE7C,MAAM,OAAO,GAAkB,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7D,KAAK;QACL,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC;KAC3B,CAAC,CAAC,CAAC;IACJ,2EAA2E;IAC3E,0EAA0E;IAC1E,4EAA4E;IAC5E,qDAAqD;IACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpB,MAAM,UAAU,GACd,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC;YACvD,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC1D,OAAO,UAAU,KAAK,CAAC;YACrB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE;YACrE,CAAC,CAAC,UAAU,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAkC;QAC5C,KAAK,EAAE,CAAC;QACR,aAAa,EAAE,CAAC;QAChB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,CAAC;QACf,GAAG,EAAE,CAAC;KACP,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,OAAO;QAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;IAErD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC;IACxE,OAAO;QACL,QAAQ;QACR,OAAO;QACP,MAAM;QACN,OAAO,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,SAAS;KAC3D,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,UAAU,CAAC,KAAoB;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC;IACpD,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACzC,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,cAAc,CAAC;AACtE,CAAC;AAED,qFAAqF;AACrF,SAAS,mBAAmB,CAC1B,QAAkB,EAClB,KAAmB,EACnB,OAAkC;IAElC,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAC1B,WAAW,CAAC,IAAI,CACd,oFAAoF;YAClF,+CAA+C,CAClD,CAAC;IACJ,CAAC;IACD,WAAW,CAAC,IAAI,CACd,uFAAuF;QACrF,yBAAyB,CAC5B,CAAC;IACF,WAAW,CAAC,IAAI,CACd,wBAAwB,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B;QACtF,wFAAwF,CAC3F,CAAC;IACF,WAAW,CAAC,IAAI,CACd,+CAA+C,QAAQ,CAAC,GAAG,CAAC,SAAS;SAClE,WAAW,EAAE;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,+DAA+D,CAC/E,CAAC;IACF,WAAW,CAAC,IAAI,CACd,0FAA0F;QACxF,kDAAkD,CACrD,CAAC;IACF,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,WAAW,CAAC,IAAI,CACd,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,WAAW,QAAQ,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,QAAQ;YAClG,yFAAyF,CAC5F,CAAC;IACJ,CAAC;IACD,4EAA4E;IAC5E,4EAA4E;IAC5E,sEAAsE;IACtE,yEAAyE;IACzE,IAAI,OAAO,KAAK,SAAS;QAAE,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/D,WAAW,CAAC,IAAI,CACd,uFAAuF,CACxF,CAAC;IAEF,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,GAAG,8CAA8C,CAAC;AAElE,MAAM,cAAc,GAAyC,MAAM,CAAC,MAAM,CAAC;IACzE,GAAG,EAAE,yBAAyB;IAC9B,GAAG,EAAE,iCAAiC;IACtC,IAAI,EAAE,mBAAmB;IACzB,MAAM,EAAE,iCAAiC;IACzC,MAAM,EAAE,eAAe;CACxB,CAAC,CAAC;AAEH,kFAAkF;AAClF,SAAS,aAAa,CAAC,QAAkB;IACvC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;IAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;IACrC,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAChF,MAAM,SAAS,GAAG,IAAI,KAAK,MAAM,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,KAAK,QAAQ,CAAC;IAEnC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,CAAC,IAAI,CACR,+FAA+F,CAChG,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CACR,4FAA4F,CAC7F,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;IAClF,IAAI,cAAc,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,cAAc,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CACR,wFAAwF;YACtF,8BAA8B,CACjC,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACtF,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAkB,EAAE,OAAsB;IACzE,MAAM,WAAW,GAA6B;QAC5C,QAAQ,EAAE,CAAC;QACX,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,CAAC;QACT,GAAG,EAAE,CAAC;QACN,QAAQ,EAAE,CAAC;KACZ,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,GAAG,EAA6B,CAAC;IACxD,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAE1B,yEAAyE;IACzE,0EAA0E;IAC1E,4EAA4E;IAC5E,8CAA8C;IAC9C,MAAM,OAAO,GACX,OAAO,CAAC,aAAa,KAAK,SAAS;QACjC,CAAC,CAAC,cAAc,CAAC,MAAM;QACvB,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAEpD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC;QAE/C,yEAAyE;QACzE,6CAA6C;QAC7C,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACxE,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxB,IAAI,KAAK,CAAC,SAAS,KAAK,UAAU;gBAAE,QAAQ,EAAE,CAAC;QACjD,CAAC;QAED,IAAI,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,EAAE,CAAC;YAC/C,iBAAiB,EAAE,CAAC;YACpB,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;YACxB,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IAEjF,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAC1D,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ;YACR,wEAAwE;YACxE,yCAAyC;YACzC,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;SAC5F,CAAC,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC;IACpC,MAAM,OAAO,GACX,iBAAiB,KAAK,CAAC,IAAI,KAAK,KAAK,SAAS;QAC5C,CAAC,CAAC,SAAS;QACX,CAAC,CAAC;YACE,KAAK,EAAE,iBAAiB;YACxB,KAAK;YACL,SAAS,EACP,GAAG,iBAAiB,SAAS,iBAAiB,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU,KAAK,YAAY;gBAC1F,GAAG,iBAAiB,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,6CAA6C;gBACtF,GAAG,iBAAiB,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,YAAY;gBACrE,GAAG,iBAAiB,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,iCAAiC;SAC7E,CAAC;IAER,MAAM,gBAAgB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpF,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAExC,sEAAsE;IACtE,2EAA2E;IAC3E,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACtD,MAAM,IAAI,SAAS,CACjB,oGAAoG,CACrG,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,MAAM,MAAM,GAAG,QAAQ,EAAE,aAAa,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,SAAS,CACjB,oEAAoE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI;YAC5F,4FAA4F,CAC/F,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,CAAC;IAC5B,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,SAAS,CACjB,iCAAiC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI;YACpE,2EAA2E;YAC3E,qEAAqE,CACxE,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,IAAI,QAAQ,EAAE,WAAW,CAAC;IAC7D,6EAA6E;IAC7E,0EAA0E;IAC1E,qEAAqE;IACrE,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,EAAE,UAAU,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACzF,MAAM,IAAI,SAAS,CACjB,sEAAsE;YACpE,wCAAwC,CAC3C,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;QACpD,QAAQ;QACR,WAAW,EAAE,OAAO,CAAC,GAAG;QACxB,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;QAC/E,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;QAClF,QAAQ,EAAE,QAAQ,IAAI,YAAY;QAClC,SAAS,EAAE,OAAO,CAAC,SAAS,KAAK,IAAI;QACrC,eAAe,EAAE,OAAO,CAAC,eAAe,KAAK,IAAI;QACjD,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;QAC/C,KAAK;QACL,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,SAAS;QACzD,WAAW,EAAE,mBAAmB,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC;QAC1D,QAAQ;QACR,QAAQ,EAAE,OAAO,CAAC,eAAe,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ;QAC3D,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QAC7C,WAAW;QACX,gBAAgB;QAChB,aAAa,EAAE,QAAQ,CAAC,GAAG,CAAC,aAAa;QACzC,QAAQ;QACR,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;KAC5C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/report/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import type { Severity } from '../severity.js';
2
+ import type { SnapshotIssue } from '../snapshot.js';
3
+ import type { ReportHeader } from './stream.js';
4
+ /**
5
+ * What a SARIF export can be asked for.
6
+ *
7
+ * Deliberately its own type rather than {@link ReportOptions}: SARIF has no
8
+ * `kind` — it is always "the issues open right now", never a retest or an
9
+ * attestation — and no branding, cover page or evidence verbosity. Accepting
10
+ * `ReportOptions` and silently ignoring most of its fields would be a worse
11
+ * API than a type that only offers what SARIF actually uses.
12
+ */
13
+ export interface SarifOptions {
14
+ /**
15
+ * Keep issues below this severity out of `results`.
16
+ *
17
+ * Unlike the other formats, there is no `omitted` count to report: SARIF
18
+ * has no prose to carry a disclosure sentence in, and a consumer asking
19
+ * for `critical` only is asking to scope a code-scanning feed, not
20
+ * reading a document that owes it an explanation of what it left out.
21
+ */
22
+ readonly severityFloor?: Severity;
23
+ }
24
+ /**
25
+ * Renders a snapshot's open issues as SARIF 2.1.0, from a header and a
26
+ * cursor — the machine path's format for GitHub code scanning (P8), and the
27
+ * streaming sibling of {@link renderJsonStream} and
28
+ * {@link renderMarkdownStream}. See {@link renderJsonStream} for the memory
29
+ * argument.
30
+ *
31
+ * **Resolved issues never appear, unconditionally — there is no
32
+ * `includeResolved` option.** SARIF is not a document a person reads; it is
33
+ * the input to GitHub's own diffing, which closes an alert when a new
34
+ * upload no longer contains it. Including a resolved issue would tell
35
+ * GitHub the finding is still open, which is the opposite of what resolving
36
+ * it meant.
37
+ *
38
+ * **Suppressed issues never appear either, and take no `suppressed`
39
+ * parameter at all.** An accepted risk is not a code-scanning alert; SARIF
40
+ * has no accepted-risk register to carry it in the way the appendix does
41
+ * for the human and other machine formats.
42
+ *
43
+ * **`ruleId` is `Issue.vulnKey`, not `Finding.sourceRuleId` or
44
+ * `sourceEngine`.** `vulnKey` is engine-independent by construction
45
+ * (`fingerprint.ts`), and naming a scanner in a customer-facing artefact is
46
+ * the thing this package's report options have twice had to stop doing
47
+ * (`ReportOptions.evidenceVerbosity`'s own TSDoc records it). `rules[]` is
48
+ * built from the same stream, deduplicated on `vulnKey` — bounded by the
49
+ * number of distinct weakness classes, not by issue count, so buffering it
50
+ * (unlike `results`) costs nothing worth avoiding.
51
+ *
52
+ * @param header - The run and the target. Never scales with issue count.
53
+ * @param issues - Every open issue, in any order — SARIF results are an
54
+ * unordered set, so this format is the one place in the streaming
55
+ * contract with no ordering requirement on its input.
56
+ * @param options - A severity floor, and nothing else.
57
+ * @returns Chunks of JSON text; concatenated, they are one SARIF document.
58
+ */
59
+ export declare function renderSarifStream(header: ReportHeader, issues: AsyncIterable<SnapshotIssue>, options?: SarifOptions): AsyncGenerator<string>;
60
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/report/sarif.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;OAOG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC;CACnC;AAyCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAuB,iBAAiB,CACtC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,EACpC,OAAO,GAAE,YAAiB,GACzB,cAAc,CAAC,MAAM,CAAC,CA8DxB"}
@@ -0,0 +1,125 @@
1
+ const SARIF_LEVEL = Object.freeze({
2
+ critical: 'error',
3
+ high: 'error',
4
+ medium: 'warning',
5
+ low: 'note',
6
+ advisory: 'note',
7
+ });
8
+ /**
9
+ * The `security-severity` GitHub code scanning reads to rank an alert, as a
10
+ * string 0.0–10.0 — GitHub's convention, not part of the SARIF spec itself.
11
+ * Fixed bands rather than a CVSS score, because not every finding has one
12
+ * and two issues at the same {@link Severity} should rank the same.
13
+ */
14
+ const SECURITY_SEVERITY = Object.freeze({
15
+ critical: '9.0',
16
+ high: '7.5',
17
+ medium: '5.0',
18
+ low: '3.0',
19
+ advisory: '1.0',
20
+ });
21
+ /** `SEVERITY_ORDER`, duplicated as an index rather than imported, to keep this file's only dependency on `severity.ts` the type. */
22
+ const FLOOR_RANK = Object.freeze({
23
+ critical: 0,
24
+ high: 1,
25
+ medium: 2,
26
+ low: 3,
27
+ advisory: 4,
28
+ });
29
+ /** `"key":value`, run through `JSON.stringify` so nothing is hand-escaped. */
30
+ function field(key, value) {
31
+ return `${JSON.stringify(key)}:${JSON.stringify(value)}`;
32
+ }
33
+ /**
34
+ * Renders a snapshot's open issues as SARIF 2.1.0, from a header and a
35
+ * cursor — the machine path's format for GitHub code scanning (P8), and the
36
+ * streaming sibling of {@link renderJsonStream} and
37
+ * {@link renderMarkdownStream}. See {@link renderJsonStream} for the memory
38
+ * argument.
39
+ *
40
+ * **Resolved issues never appear, unconditionally — there is no
41
+ * `includeResolved` option.** SARIF is not a document a person reads; it is
42
+ * the input to GitHub's own diffing, which closes an alert when a new
43
+ * upload no longer contains it. Including a resolved issue would tell
44
+ * GitHub the finding is still open, which is the opposite of what resolving
45
+ * it meant.
46
+ *
47
+ * **Suppressed issues never appear either, and take no `suppressed`
48
+ * parameter at all.** An accepted risk is not a code-scanning alert; SARIF
49
+ * has no accepted-risk register to carry it in the way the appendix does
50
+ * for the human and other machine formats.
51
+ *
52
+ * **`ruleId` is `Issue.vulnKey`, not `Finding.sourceRuleId` or
53
+ * `sourceEngine`.** `vulnKey` is engine-independent by construction
54
+ * (`fingerprint.ts`), and naming a scanner in a customer-facing artefact is
55
+ * the thing this package's report options have twice had to stop doing
56
+ * (`ReportOptions.evidenceVerbosity`'s own TSDoc records it). `rules[]` is
57
+ * built from the same stream, deduplicated on `vulnKey` — bounded by the
58
+ * number of distinct weakness classes, not by issue count, so buffering it
59
+ * (unlike `results`) costs nothing worth avoiding.
60
+ *
61
+ * @param header - The run and the target. Never scales with issue count.
62
+ * @param issues - Every open issue, in any order — SARIF results are an
63
+ * unordered set, so this format is the one place in the streaming
64
+ * contract with no ordering requirement on its input.
65
+ * @param options - A severity floor, and nothing else.
66
+ * @returns Chunks of JSON text; concatenated, they are one SARIF document.
67
+ */
68
+ export async function* renderSarifStream(header, issues, options = {}) {
69
+ const floor = options.severityFloor;
70
+ const floorAt = floor === undefined ? 4 : FLOOR_RANK[floor];
71
+ // Small — bounded by distinct weakness classes, not by issue count — and
72
+ // known only once the stream is exhausted. So `results` (the one array
73
+ // that must never be buffered) is written first and `tool.driver.rules`
74
+ // last, the one key order that lets both be true without a second pass
75
+ // over `issues`: JSON does not care which key comes first.
76
+ const rules = new Map();
77
+ yield '{';
78
+ // The schema's own `id`, not a GitHub raw link — checked by hand, because
79
+ // an unreachable $schema is a broken document a validator would still call
80
+ // valid, and getting it wrong once cost the trip to the OASIS repo to
81
+ // learn its real path (`tests/fixtures/README.md` records that trip).
82
+ yield field('$schema', 'https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json');
83
+ yield ',' + field('version', '2.1.0');
84
+ yield ',"runs":[{"results":[';
85
+ let firstResult = true;
86
+ for await (const entry of issues) {
87
+ const { issue } = entry;
88
+ if (issue.status === 'resolved')
89
+ continue;
90
+ if (FLOOR_RANK[issue.effectiveSeverity] > floorAt)
91
+ continue;
92
+ if (!rules.has(issue.vulnKey)) {
93
+ rules.set(issue.vulnKey, { title: issue.title, cwe: issue.cwe });
94
+ }
95
+ const message = entry.findings[0]?.description ?? issue.title;
96
+ const result = {
97
+ ruleId: issue.vulnKey,
98
+ level: SARIF_LEVEL[issue.effectiveSeverity],
99
+ message: { text: message },
100
+ locations: [
101
+ {
102
+ physicalLocation: {
103
+ artifactLocation: { uri: issue.location },
104
+ },
105
+ },
106
+ ],
107
+ partialFingerprints: { secureportFingerprint: issue.fingerprint },
108
+ properties: { 'security-severity': SECURITY_SEVERITY[issue.effectiveSeverity] },
109
+ };
110
+ yield (firstResult ? '' : ',') + JSON.stringify(result);
111
+ firstResult = false;
112
+ }
113
+ yield ']';
114
+ const ruleDefs = [...rules.entries()].map(([vulnKey, rule]) => ({
115
+ id: vulnKey,
116
+ shortDescription: { text: rule.title },
117
+ ...(rule.cwe === undefined ? {} : { properties: { tags: [rule.cwe] } }),
118
+ }));
119
+ yield ',"tool":{"driver":{';
120
+ yield field('name', 'Secureport');
121
+ yield ',' + field('informationUri', 'https://secureport.io/');
122
+ yield ',"rules":' + JSON.stringify(ruleDefs);
123
+ yield '}}}]}';
124
+ }
125
+ //# sourceMappingURL=sarif.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.js","sourceRoot":"","sources":["../../src/report/sarif.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ import type { RunSummary } from '../run.js';
2
+ import type { SnapshotIssue, SuppressedIssue, Target } from '../snapshot.js';
3
+ import { type ReportOptions } from './model.js';
4
+ /**
5
+ * Everything a streaming machine-readable report needs that is not per-issue.
6
+ *
7
+ * **Deliberately not a {@link Snapshot}.** A `Snapshot`'s `issues` and
8
+ * `suppressed` are eagerly-materialised arrays — the right shape for PDF and
9
+ * HTML, which are queued, capped at 500 issues, and fully in memory before
10
+ * Chromium ever runs. The machine formats have no such cap, so their
11
+ * assembler must never hold every issue at once; a `ReportHeader` carries
12
+ * only the handful of fields that do not scale with issue count, and the
13
+ * issues themselves arrive as an `AsyncIterable`.
14
+ */
15
+ export interface ReportHeader {
16
+ /** The run this report describes. */
17
+ readonly run: RunSummary;
18
+ /** What to compare against, for a retest. Absent for a first run. */
19
+ readonly baseline?: RunSummary;
20
+ /** The system under test. */
21
+ readonly target: Target;
22
+ }
23
+ /**
24
+ * Renders a report as JSON, from a header and a cursor over its issues,
25
+ * rather than from a fully-assembled {@link Snapshot}.
26
+ *
27
+ * **This is the machine path's whole reason to exist (B124).** `renderJson`
28
+ * holds every issue in one array before `JSON.stringify` walks it — measured
29
+ * at 239 MiB for 25,000 issues — so memory scales with the result and three
30
+ * concurrent exports exhaust a 512 MiB instance. This function instead
31
+ * yields the document a fragment at a time: everything that does not depend
32
+ * on having seen every issue is emitted immediately, the `issues` and
33
+ * `suppressed` arrays are written one element per row as the cursors
34
+ * produce them, and the handful of fields that need a full pass —
35
+ * `basis.includesManual`, `breached`, `omitted`, the retest counts — are
36
+ * accumulated in a fold whose state is a few counters, never the issues
37
+ * themselves, and written once both cursors are exhausted. Concatenating
38
+ * every yielded chunk produces one JSON document; nothing here buffers it
39
+ * as a string first.
40
+ *
41
+ * **`sections` grouped by severity and the sorted `resolved` list do not
42
+ * exist here.** Both require holding the whole array to sort; this function
43
+ * instead trusts that `issues` and `suppressed` already arrive in the order
44
+ * the document should show them; a cursor-based caller supplies that with a
45
+ * SQL `ORDER BY`, not with an in-memory sort. `includeResolved` and
46
+ * `severityFloor` still apply, filtering rows out of the stream rather than
47
+ * out of an array.
48
+ *
49
+ * @param header - The run, its baseline, and the target. Never scales with
50
+ * issue count.
51
+ * @param issues - Every issue in scope, most urgent first, in the order the
52
+ * document should list them.
53
+ * @param suppressed - The accepted-risk register, in the order the appendix
54
+ * should list it.
55
+ * @param options - Which report, attribution, and the render time.
56
+ * @returns Chunks of JSON text; concatenated, they are one document.
57
+ */
58
+ export declare function renderJsonStream(header: ReportHeader, issues: AsyncIterable<SnapshotIssue>, suppressed: AsyncIterable<SuppressedIssue>, options: ReportOptions): AsyncGenerator<string>;
59
+ /**
60
+ * Renders a report as Markdown, from a header and a cursor over its issues,
61
+ * rather than from a fully-assembled {@link Snapshot}. The streaming sibling
62
+ * of {@link renderJsonStream} — see it for the memory argument, which applies
63
+ * here identically: `renderMarkdown` holds every issue in one array before
64
+ * formatting any of it.
65
+ *
66
+ * **The document is reordered relative to `renderMarkdown`, and that is
67
+ * forced rather than stylistic.** The array-based renderer opens with "Basis
68
+ * of testing" and a "What changed" line naming how many issues are past
69
+ * their remediation deadline — both need to know something about *every*
70
+ * issue (`basis.includesManual`, `breached`) before the first line can be
71
+ * printed, which a forward-only stream cannot offer without buffering
72
+ * everything first. So this function prints what it already knows up front
73
+ * (title, scope, the New/Still open/Regressed/Resolved/Suppressed table,
74
+ * which all read straight off `RunSummary`) and moves everything that needs
75
+ * a full pass — the basis statement, the remediation-deadline count, what a
76
+ * severity floor omitted, the retest verdict counts — into a closing
77
+ * `## Summary` section, written once both cursors are exhausted.
78
+ *
79
+ * **`sections` grouped by severity do not exist here**, for the reason given
80
+ * in {@link renderJsonStream}: `issues` and `suppressed` are trusted to
81
+ * already arrive in the order the document should show them. For a `pen`
82
+ * report that means a severity sub-heading appears whenever the incoming
83
+ * severity changes, without the issue count that heading carries in
84
+ * `renderMarkdown` — the count is not known until the section ends. A
85
+ * `retest` report's per-issue table has no severity floor applied to it,
86
+ * matching `renderMarkdown`: the whole point of that table is showing what
87
+ * happened to every issue carried into the retest, not a curated subset.
88
+ *
89
+ * **`attest` buffers its suppressed list; nothing else buffers issues.** An
90
+ * Attestation Letter states counts and names nobody's individual issue, so
91
+ * it folds the whole `issues` cursor for those counts without printing a
92
+ * row — but it also prints the suppressed appendix *after* that letter body,
93
+ * by which point the `suppressed` cursor would already be exhausted. Holding
94
+ * that one list (the accepted-risk register, ordinarily a minority of the
95
+ * total) is the one deliberate exception to "never hold more than a row".
96
+ *
97
+ * @param header - The run, its baseline, and the target. Never scales with
98
+ * issue count.
99
+ * @param issues - Every issue in scope, most urgent first: open/regressed
100
+ * before resolved, each group by severity then most-recently-seen first —
101
+ * the order the document lists them in.
102
+ * @param suppressed - The accepted-risk register, in the order the appendix
103
+ * should list it.
104
+ * @param options - Which report, attribution, and the render time.
105
+ * @returns Chunks of Markdown text; concatenated, they are one document.
106
+ */
107
+ export declare function renderMarkdownStream(header: ReportHeader, issues: AsyncIterable<SnapshotIssue>, suppressed: AsyncIterable<SuppressedIssue>, options: ReportOptions): AsyncGenerator<string>;
108
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/report/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EASL,KAAK,aAAa,EAEnB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IAEzB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAE/B,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAoED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAuB,gBAAgB,CACrC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,EACpC,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC,EAC1C,OAAO,EAAE,aAAa,GACrB,cAAc,CAAC,MAAM,CAAC,CAoGxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAuB,oBAAoB,CACzC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,EACpC,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC,EAC1C,OAAO,EAAE,aAAa,GACrB,cAAc,CAAC,MAAM,CAAC,CA6TxB"}