@tracelane/report 0.1.0-alpha.2 → 0.1.0-alpha.20

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 (67) hide show
  1. package/NOTICE +8 -0
  2. package/README.md +33 -5
  3. package/dist/_security/detectors/insecure-cookies.d.ts +4 -0
  4. package/dist/_security/detectors/insecure-cookies.d.ts.map +1 -0
  5. package/dist/_security/detectors/insecure-cookies.js +32 -0
  6. package/dist/_security/detectors/insecure-cookies.js.map +1 -0
  7. package/dist/_security/detectors/missing-headers.d.ts +4 -0
  8. package/dist/_security/detectors/missing-headers.d.ts.map +1 -0
  9. package/dist/_security/detectors/missing-headers.js +36 -0
  10. package/dist/_security/detectors/missing-headers.js.map +1 -0
  11. package/dist/_security/detectors/mixed-content.d.ts +5 -0
  12. package/dist/_security/detectors/mixed-content.d.ts.map +1 -0
  13. package/dist/_security/detectors/mixed-content.js +74 -0
  14. package/dist/_security/detectors/mixed-content.js.map +1 -0
  15. package/dist/_security/detectors/reverse-tabnabbing.d.ts +10 -0
  16. package/dist/_security/detectors/reverse-tabnabbing.d.ts.map +1 -0
  17. package/dist/_security/detectors/reverse-tabnabbing.js +44 -0
  18. package/dist/_security/detectors/reverse-tabnabbing.js.map +1 -0
  19. package/dist/_security/index.d.ts +29 -0
  20. package/dist/_security/index.d.ts.map +1 -0
  21. package/dist/_security/index.js +36 -0
  22. package/dist/_security/index.js.map +1 -0
  23. package/dist/_security/response-meta.d.ts +28 -0
  24. package/dist/_security/response-meta.d.ts.map +1 -0
  25. package/dist/_security/response-meta.js +50 -0
  26. package/dist/_security/response-meta.js.map +1 -0
  27. package/dist/_security/serialized-dom.d.ts +20 -0
  28. package/dist/_security/serialized-dom.d.ts.map +1 -0
  29. package/dist/_security/serialized-dom.js +32 -0
  30. package/dist/_security/serialized-dom.js.map +1 -0
  31. package/dist/_security/suppress.d.ts +7 -0
  32. package/dist/_security/suppress.d.ts.map +1 -0
  33. package/dist/_security/suppress.js +8 -0
  34. package/dist/_security/suppress.js.map +1 -0
  35. package/dist/assets.d.ts +20 -0
  36. package/dist/assets.d.ts.map +1 -1
  37. package/dist/assets.js +60 -6
  38. package/dist/assets.js.map +1 -1
  39. package/dist/build-report.d.ts +19 -0
  40. package/dist/build-report.d.ts.map +1 -1
  41. package/dist/build-report.js +20 -2
  42. package/dist/build-report.js.map +1 -1
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +3 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/markdown.d.ts +2 -1
  48. package/dist/markdown.d.ts.map +1 -1
  49. package/dist/markdown.js +11 -1
  50. package/dist/markdown.js.map +1 -1
  51. package/dist/metadata.d.ts +21 -2
  52. package/dist/metadata.d.ts.map +1 -1
  53. package/dist/metadata.js +98 -27
  54. package/dist/metadata.js.map +1 -1
  55. package/dist/panels.d.ts +40 -5
  56. package/dist/panels.d.ts.map +1 -1
  57. package/dist/panels.js +175 -23
  58. package/dist/panels.js.map +1 -1
  59. package/dist/report-writer.d.ts +43 -0
  60. package/dist/report-writer.d.ts.map +1 -0
  61. package/dist/report-writer.js +65 -0
  62. package/dist/report-writer.js.map +1 -0
  63. package/dist/template.d.ts +19 -0
  64. package/dist/template.d.ts.map +1 -1
  65. package/dist/template.js +987 -72
  66. package/dist/template.js.map +1 -1
  67. package/package.json +28 -7
package/dist/assets.js CHANGED
@@ -1,10 +1,12 @@
1
- // Build-time asset loaders (Task 2.8 + 2.9).
1
+ // Build-time asset loaders (Task 2.8 + 2.9 + Phase 6 report-revamp fonts).
2
2
  //
3
- // The self-contained report inlines three vendored assets so it opens fully
4
- // offline with nothing fetched at view time:
5
- // 1. the rrweb-player UMD (defines `window.rrwebPlayer`) — Task 2.8
6
- // 2. the rrweb-player CSS — Task 2.8
7
- // 3. the fflate UMD gunzip (defines `window.fflate`) — Task 2.9
3
+ // The self-contained report inlines vendored assets so it opens fully offline
4
+ // with nothing fetched at view time:
5
+ // 1. the rrweb-player UMD (defines `window.rrwebPlayer`) — Task 2.8
6
+ // 2. the rrweb-player CSS — Task 2.8
7
+ // 3. the fflate UMD gunzip (defines `window.fflate`) — Task 2.9
8
+ // 4. Fraunces Variable (latin, weight 100-900, normal + italic) — Phase 6
9
+ // 5. JetBrains Mono Variable (latin, weight 100-800, normal) — Phase 6
8
10
  //
9
11
  // Each is read from the installed package via `require.resolve`, NOT hand-pasted
10
12
  // into source (the assets are large and would bloat/obscure the diff, and they
@@ -70,4 +72,56 @@ export function loadPlayerCss() {
70
72
  export function loadFflateGunzipSource() {
71
73
  return readUmdViaUnpkg('fflate');
72
74
  }
75
+ // ---------------------------------------------------------------------------
76
+ // Font assets (Phase 6 report-revamp).
77
+ //
78
+ // The new report design pairs Fraunces (serif, OFL-1.1) for the hero "what
79
+ // failed" headline + section heads with JetBrains Mono (mono, OFL-1.1) for all
80
+ // data rows. Both are read as variable-axis woff2 files from `@fontsource-
81
+ // variable/*` and embedded as base64 `url(data:font/woff2;base64,…)` inside the
82
+ // SHELL_CSS `@font-face` rules — same offline-first posture as the player UMD.
83
+ // ---------------------------------------------------------------------------
84
+ /**
85
+ * Read a woff2 file out of an `@fontsource-variable/*` package and return its
86
+ * base64-encoded contents. The fontsource packages don't expose the woff2
87
+ * files via their `exports` map directly (the `./files/*.woff2` mapping uses a
88
+ * glob), so we walk to the file via the package's own `package.json` path.
89
+ */
90
+ function readFontBase64(packageName, fileName) {
91
+ const pkgJsonPath = localRequire.resolve(`${packageName}/package.json`);
92
+ const pkgDirUrl = pathToFileURL(pkgJsonPath.slice(0, pkgJsonPath.lastIndexOf('/') + 1));
93
+ const fontUrl = new URL(`./files/${fileName}`, pkgDirUrl);
94
+ const fontPath = fileURLToPath(fontUrl);
95
+ const pkgDirPath = fileURLToPath(pkgDirUrl);
96
+ if (!fontPath.startsWith(pkgDirPath)) {
97
+ throw new Error(`${packageName}: font file escapes the package directory`);
98
+ }
99
+ return readFileSync(fontPath).toString('base64');
100
+ }
101
+ /**
102
+ * Fraunces Variable (weight axis 100-900, latin charset, normal style).
103
+ * SIL OFL-1.1 — credited in NOTICE. ~36 KB raw → ~49 KB base64.
104
+ */
105
+ export function loadFrauncesNormal() {
106
+ return readFontBase64('@fontsource-variable/fraunces', 'fraunces-latin-wght-normal.woff2');
107
+ }
108
+ /**
109
+ * Fraunces Variable (weight axis 100-900, latin charset, italic style).
110
+ * Same package + license as the normal weight; ~45 KB raw → ~60 KB base64.
111
+ * Used for the headline's emphasized clause and the section heads.
112
+ */
113
+ export function loadFrauncesItalic() {
114
+ return readFontBase64('@fontsource-variable/fraunces', 'fraunces-latin-wght-italic.woff2');
115
+ }
116
+ /**
117
+ * JetBrains Mono Variable (weight axis 100-800, latin charset, normal style).
118
+ * SIL OFL-1.1 — credited in NOTICE. ~40 KB raw → ~54 KB base64.
119
+ *
120
+ * Italic intentionally NOT loaded — the data rows (console + network + meta
121
+ * strip + timestamps) never use italics, so the second 43 KB italic woff2
122
+ * would add weight to every report for no design benefit.
123
+ */
124
+ export function loadJetBrainsMonoNormal() {
125
+ return readFontBase64('@fontsource-variable/jetbrains-mono', 'jetbrains-mono-latin-wght-normal.woff2');
126
+ }
73
127
  //# sourceMappingURL=assets.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,4EAA4E;AAC5E,6CAA6C;AAC7C,yEAAyE;AACzE,0EAA0E;AAC1E,0EAA0E;AAC1E,EAAE;AACF,iFAAiF;AACjF,+EAA+E;AAC/E,+EAA+E;AAC/E,mDAAmD;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAExD,6EAA6E;AAC7E,8EAA8E;AAC9E,iEAAiE;AACjE,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEpD,SAAS,SAAS,CAAC,SAAiB;IAClC,OAAO,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CAAC,WAAmB;IAC1C,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,WAAW,eAAe,CAAC,CAAC;IACxE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAuB,CAAC;IAChF,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IACxB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,GAAG,WAAW,mDAAmD,CAAC,CAAC;IACrF,CAAC;IACD,6EAA6E;IAC7E,+CAA+C;IAC/C,MAAM,SAAS,GAAG,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxF,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,GAAG,WAAW,+CAA+C,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,SAAS,CAAC,4BAA4B,CAAC,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,SAAS,CAAC,6BAA6B,CAAC,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { eventWithTime } from '@cubenest/rrweb-core';
2
+ import type { Suppression } from './_security/index.js';
2
3
  import type { ReportMeta } from './types.js';
3
4
  /** Options for {@link buildReport}. */
4
5
  export interface BuildReportOptions {
@@ -7,6 +8,24 @@ export interface BuildReportOptions {
7
8
  * Pass `false` only when the caller has already applied the size guard.
8
9
  */
9
10
  enforceSizeBudget?: boolean;
11
+ /**
12
+ * Render the self-marketing footer in the report. Default true. Pass `false`
13
+ * to suppress it (surfaces the wdio `report: { footer: false }` opt-out —
14
+ * audit A-8).
15
+ */
16
+ footer?: boolean;
17
+ /**
18
+ * Run the advisory `@tracelane/security` analyzer over the captured stream
19
+ * and surface its findings in the report (Markdown section + collapsed
20
+ * panel). Default true. Pass `false` to skip analysis entirely — `analyze`
21
+ * is not called and nothing security-related is rendered.
22
+ */
23
+ security?: boolean;
24
+ /**
25
+ * Suppressions forwarded to the analyzer (e.g. silence a known-acceptable
26
+ * signal/url). Ignored when `security` is `false`.
27
+ */
28
+ securitySuppress?: Suppression[];
10
29
  }
11
30
  /**
12
31
  * Build a self-contained HTML report for one test run.
@@ -1 +1 @@
1
- {"version":3,"file":"build-report.d.ts","sourceRoot":"","sources":["../src/build-report.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAO1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,aAAa,EAAE,EACvB,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAsBR"}
1
+ {"version":3,"file":"build-report.d.ts","sourceRoot":"","sources":["../src/build-report.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,WAAW,EAAE,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,aAAa,EAAE,EACvB,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CA6CR"}
@@ -14,6 +14,7 @@
14
14
  // exceeds the 25 MB budget (ADR-0005); the report renders a banner when a prune
15
15
  // fired so the truncation is visible to the user.
16
16
  import { pruneToSizeBudget } from '@tracelane/core';
17
+ import { analyze } from './_security/index.js';
17
18
  import { encodeEventsBlob } from './embed.js';
18
19
  import { buildMarkdown, extractActionLog } from './markdown.js';
19
20
  import { resolveCiMetadata } from './metadata.js';
@@ -27,7 +28,7 @@ import { renderReportHtml } from './template.js';
27
28
  * @returns a complete `.html` document string — write it to disk as-is
28
29
  */
29
30
  export function buildReport(events, meta, options = {}) {
30
- const { enforceSizeBudget = true } = options;
31
+ const { enforceSizeBudget = true, footer = true, security = true, securitySuppress = [], } = options;
31
32
  // Keep the report within budget; surface a banner if anything was dropped.
32
33
  const { events: sized, pruned } = enforceSizeBudget
33
34
  ? pruneToSizeBudget(events)
@@ -36,14 +37,31 @@ export function buildReport(events, meta, options = {}) {
36
37
  const consoleRows = extractConsole(sized);
37
38
  const networkRows = extractNetwork(sized);
38
39
  const actions = extractActionLog(sized);
39
- const markdown = buildMarkdown(resolvedMeta, consoleRows, networkRows, actions);
40
+ // Advisory security-hygiene analysis (default on). Runs over the SAME
41
+ // size-pruned events the other extractors consume; skipped when disabled.
42
+ const securityFindings = security
43
+ ? analyze(sized, { suppress: securitySuppress })
44
+ : [];
45
+ const markdown = buildMarkdown(resolvedMeta, consoleRows, networkRows, actions, securityFindings);
46
+ // First/last event timestamps drive the hero meta strip's "Events" item,
47
+ // the replay-header session-range label, and the failure marker on the
48
+ // custom timeline strip. `?? 0` fallback covers the crashed-before-
49
+ // recorder-snapshot path (sized empty) — optional chaining + nullish
50
+ // coalescing keep the type-safety without a non-null assertion.
51
+ const firstTs = sized[0]?.timestamp ?? 0;
52
+ const lastTs = sized[sized.length - 1]?.timestamp ?? 0;
40
53
  return renderReportHtml({
41
54
  meta: resolvedMeta,
42
55
  eventsGzB64: encodeEventsBlob(sized),
43
56
  console: consoleRows,
44
57
  network: networkRows,
58
+ security: securityFindings,
45
59
  markdown,
46
60
  pruned,
61
+ eventCount: sized.length,
62
+ firstTs,
63
+ lastTs,
64
+ footer,
47
65
  });
48
66
  }
49
67
  //# sourceMappingURL=build-report.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-report.js","sourceRoot":"","sources":["../src/build-report.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAC9E,wCAAwC;AACxC,yEAAyE;AACzE,gEAAgE;AAChE,iEAAiE;AACjE,iEAAiE;AACjE,iEAAiE;AACjE,iDAAiD;AACjD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,kDAAkD;AAGlD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAYjD;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,MAAuB,EACvB,IAAgB,EAChB,UAA8B,EAAE;IAEhC,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAE7C,2EAA2E;IAC3E,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,iBAAiB;QACjD,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC;QAC3B,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAE9B,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,aAAa,CAAC,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAEhF,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,gBAAgB,CAAC,KAAK,CAAC;QACpC,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,WAAW;QACpB,QAAQ;QACR,MAAM;KACP,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"build-report.js","sourceRoot":"","sources":["../src/build-report.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAC9E,wCAAwC;AACxC,yEAAyE;AACzE,gEAAgE;AAChE,iEAAiE;AACjE,iEAAiE;AACjE,iEAAiE;AACjE,iDAAiD;AACjD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,kDAAkD;AAGlD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AA8BjD;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,MAAuB,EACvB,IAAgB,EAChB,UAA8B,EAAE;IAEhC,MAAM,EACJ,iBAAiB,GAAG,IAAI,EACxB,MAAM,GAAG,IAAI,EACb,QAAQ,GAAG,IAAI,EACf,gBAAgB,GAAG,EAAE,GACtB,GAAG,OAAO,CAAC;IAEZ,2EAA2E;IAC3E,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,iBAAiB;QACjD,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC;QAC3B,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAE9B,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACxC,sEAAsE;IACtE,0EAA0E;IAC1E,MAAM,gBAAgB,GAAsB,QAAQ;QAClD,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAChD,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,QAAQ,GAAG,aAAa,CAAC,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAElG,yEAAyE;IACzE,uEAAuE;IACvE,oEAAoE;IACpE,qEAAqE;IACrE,gEAAgE;IAChE,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,SAAS,IAAI,CAAC,CAAC;IAEvD,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,gBAAgB,CAAC,KAAK,CAAC;QACpC,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,WAAW;QACpB,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ;QACR,MAAM;QACN,UAAU,EAAE,KAAK,CAAC,MAAM;QACxB,OAAO;QACP,MAAM;QACN,MAAM;KACP,CAAC,CAAC;AACL,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  export { buildReport } from './build-report.js';
2
2
  export type { BuildReportOptions } from './build-report.js';
3
3
  export type { ReportMeta, ReportStatus, Viewport } from './types.js';
4
+ export { reportFileName, slugify, specSlug, writeReport } from './report-writer.js';
5
+ export type { WriteReportInput } from './report-writer.js';
4
6
  export { decodeEventsBlob, encodeEventsBlob } from './embed.js';
5
7
  export { extractConsole, extractNetwork, CONSOLE_PLUGIN, NETWORK_EVENT_TAG, NETWORK_CONSOLE_PREFIX, } from './panels.js';
6
8
  export type { ConsoleEntry, NetworkEntry } from './panels.js';
7
9
  export { resolveCiMetadata } from './metadata.js';
8
10
  export { buildMarkdown, extractActionLog, MAX_CONSOLE_MESSAGES, MAX_ACTIONS } from './markdown.js';
9
11
  export type { ActionEntry } from './markdown.js';
12
+ export type { SecurityFinding, Severity, SecuritySignal, Suppression } from './_security/index.js';
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGrE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGhE,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACnG,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAIrE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACpF,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGhE,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACnG,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAKjD,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  // Public API surface for @tracelane/report.
2
2
  // The report builder: events + metadata -> self-contained offline HTML string.
3
3
  export { buildReport } from './build-report.js';
4
+ // Disk writer: build the HTML and write it under outDir with a parallel-safe,
5
+ // adapter-namespaced filename. Shared by the WDIO and Playwright adapters.
6
+ export { reportFileName, slugify, specSlug, writeReport } from './report-writer.js';
4
7
  // Events blob round-trip (Task 2.9) — useful for re-reading a report's events.
5
8
  export { decodeEventsBlob, encodeEventsBlob } from './embed.js';
6
9
  // Console + network panel extraction (Task 2.10).
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAE5C,+EAA+E;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAMhD,+EAA+E;AAC/E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE,kDAAkD;AAClD,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAGrB,sCAAsC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,wCAAwC;AACxC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAE5C,+EAA+E;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAMhD,8EAA8E;AAC9E,2EAA2E;AAC3E,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGpF,+EAA+E;AAC/E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE,kDAAkD;AAClD,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAGrB,sCAAsC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,wCAAwC;AACxC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { eventWithTime } from '@cubenest/rrweb-core';
2
+ import type { SecurityFinding } from './_security/index.js';
2
3
  import type { ConsoleEntry, NetworkEntry } from './panels.js';
3
4
  import type { ReportMeta } from './types.js';
4
5
  /** Max console messages included in the prompt (P1 PRD §F.3: "last 30"). */
@@ -18,5 +19,5 @@ export interface ActionEntry {
18
19
  */
19
20
  export declare function extractActionLog(events: readonly eventWithTime[]): ActionEntry[];
20
21
  /** Build the Markdown prompt (P1 PRD §F.3). */
21
- export declare function buildMarkdown(meta: ReportMeta, consoleRows: readonly ConsoleEntry[], networkRows: readonly NetworkEntry[], actions: readonly ActionEntry[]): string;
22
+ export declare function buildMarkdown(meta: ReportMeta, consoleRows: readonly ConsoleEntry[], networkRows: readonly NetworkEntry[], actions: readonly ActionEntry[], securityFindings?: readonly SecurityFinding[]): string;
22
23
  //# sourceMappingURL=markdown.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,uEAAuE;AACvE,eAAO,MAAM,WAAW,KAAK,CAAC;AAE9B,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAqBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,WAAW,EAAE,CAsBhF;AAMD,+CAA+C;AAC/C,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,SAAS,YAAY,EAAE,EACpC,WAAW,EAAE,SAAS,YAAY,EAAE,EACpC,OAAO,EAAE,SAAS,WAAW,EAAE,GAC9B,MAAM,CA4CR"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,uEAAuE;AACvE,eAAO,MAAM,WAAW,KAAK,CAAC;AAE9B,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAqBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,WAAW,EAAE,CAsBhF;AAMD,+CAA+C;AAC/C,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,SAAS,YAAY,EAAE,EACpC,WAAW,EAAE,SAAS,YAAY,EAAE,EACpC,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,gBAAgB,GAAE,SAAS,eAAe,EAAO,GAChD,MAAM,CAuDR"}
package/dist/markdown.js CHANGED
@@ -54,7 +54,7 @@ function bullet(line) {
54
54
  return `- ${line}`;
55
55
  }
56
56
  /** Build the Markdown prompt (P1 PRD §F.3). */
57
- export function buildMarkdown(meta, consoleRows, networkRows, actions) {
57
+ export function buildMarkdown(meta, consoleRows, networkRows, actions, securityFindings = []) {
58
58
  const out = [];
59
59
  out.push('## Failing test');
60
60
  out.push(bullet(`Spec: ${meta.spec ?? '(unknown)'}`));
@@ -96,6 +96,16 @@ export function buildMarkdown(meta, consoleRows, networkRows, actions) {
96
96
  else {
97
97
  lastActions.forEach((a, i) => out.push(`${i + 1}. ${a.description}`));
98
98
  }
99
+ // Advisory security-hygiene section — additive, omitted entirely when there
100
+ // are no findings (Task 10). These are observations, NOT a security audit.
101
+ if (securityFindings.length > 0) {
102
+ out.push('');
103
+ out.push('## Security hygiene (advisory)');
104
+ out.push('_Observed during the test run — advisory hygiene signals, not a security audit._');
105
+ for (const s of securityFindings) {
106
+ out.push(bullet(`[${s.severity}] ${s.title} — ${s.evidence}`));
107
+ }
108
+ }
99
109
  return `${out.join('\n')}\n`;
100
110
  }
101
111
  //# sourceMappingURL=markdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,25 @@ import type { ReportMeta } from './types.js';
4
4
  * absent. Explicit values always win; auto-detection only fills gaps.
5
5
  */
6
6
  export declare function resolveCiMetadata(meta: ReportMeta): ReportMeta;
7
- /** Render the metadata header markup (P1 PRD §F.1). */
8
- export declare function renderMetaHeader(meta: ReportMeta): string;
7
+ /**
8
+ * Render the new hero + meta-strip (Phase 6).
9
+ *
10
+ * Replaces the old `<header class="meta">` shape. The visible structure:
11
+ *
12
+ * <section class="hero">
13
+ * <div class="eyebrow">…status pill + spec + duration + browser…</div>
14
+ * <h1 class="what">…title with <em> emphasized inside…</h1>
15
+ * <pre class="error-message">…verbatim error stack trace…</pre>
16
+ * <div class="meta-strip">…6 small key-value items…</div>
17
+ * </section>
18
+ *
19
+ * The status pill keeps `class="status <status>"` so existing test assertions
20
+ * for "class=\"status failed\"" still match; the commit value still ships
21
+ * inside `<code>` and the buildUrl still becomes an `<a href="…">` for safe
22
+ * URLs only.
23
+ *
24
+ * `eventCount` is rendered when non-undefined; the caller (template.ts) passes
25
+ * `events.length` after `pruneToSizeBudget` runs.
26
+ */
27
+ export declare function renderHero(meta: ReportMeta, eventCount?: number, capturedAt?: Date): string;
9
28
  //# sourceMappingURL=metadata.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA4B7C;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAQ9D;AA8BD,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CA2BzD"}
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA4B7C;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAQ9D;AAwDD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAyD3F"}
package/dist/metadata.js CHANGED
@@ -1,11 +1,14 @@
1
- // Metadata header (Task 2.11).
1
+ // Metadata header (Task 2.11 + Phase 6 hero rewrite).
2
2
  //
3
3
  // Two responsibilities:
4
4
  // • resolveCiMetadata — fill commit SHA + build URL from CI env vars when the
5
5
  // caller didn't supply them (GITHUB_SHA / CI_COMMIT_SHA, and common build
6
6
  // URL conventions for GitHub Actions + GitLab CI).
7
- // • renderMetaHeader — the <header class="meta"> markup (spec, title, status,
8
- // duration, browser, viewport, commit, build URL), HTML-escaped.
7
+ // • renderHero — the new editorial-postmortem `<section class="hero">` markup:
8
+ // eyebrow strip (status + spec + duration + browser), serif headline with
9
+ // the test title + status framing, monospace error block, then the
10
+ // `.meta-strip` of small key-value pairs (spec / commit / build / captured /
11
+ // events). HTML-escaped throughout; javascript: URLs become text, not links.
9
12
  import { escapeHtml } from './html.js';
10
13
  /** Read an env var without a hard `@types/node` dependency (platform-light). */
11
14
  function readEnv(name) {
@@ -54,9 +57,6 @@ function formatDuration(ms) {
54
57
  const m = Math.floor(s / 60);
55
58
  return `${m}m ${Math.round(s - m * 60)}s`;
56
59
  }
57
- function row(term, value) {
58
- return `<dt>${escapeHtml(term)}</dt><dd>${value}</dd>`;
59
- }
60
60
  /**
61
61
  * Whether `url` is safe to use as an `href`. Only http(s) — blocks `javascript:`,
62
62
  * `data:`, `vbscript:` etc. The build URL is sourced from CI env vars
@@ -73,33 +73,104 @@ function isSafeUrl(url) {
73
73
  return false;
74
74
  }
75
75
  }
76
- /** Render the metadata header markup (P1 PRD §F.1). */
77
- export function renderMetaHeader(meta) {
78
- const rows = [];
76
+ /** A status's human-facing display verb in the headline ("failed" "failed"). */
77
+ function statusVerb(status) {
78
+ switch (status) {
79
+ case 'failed':
80
+ return 'failed';
81
+ case 'broken':
82
+ return 'errored';
83
+ case 'passed':
84
+ return 'passed';
85
+ case 'skipped':
86
+ return 'was skipped';
87
+ default:
88
+ return status;
89
+ }
90
+ }
91
+ /** Format an ISO timestamp into a compact "2026-05-30 18:47 UTC" rendering. */
92
+ function formatCapturedAt(d) {
93
+ const pad = (n) => String(n).padStart(2, '0');
94
+ return (`${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ` +
95
+ `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())} UTC`);
96
+ }
97
+ /** Build one `.meta-strip .item` block: label + value, value may contain HTML. */
98
+ function stripItem(label, valueHtml) {
99
+ return `<div class="item"><span class="label">${escapeHtml(label)}</span><span class="value">${valueHtml}</span></div>`;
100
+ }
101
+ /**
102
+ * Render the new hero + meta-strip (Phase 6).
103
+ *
104
+ * Replaces the old `<header class="meta">` shape. The visible structure:
105
+ *
106
+ * <section class="hero">
107
+ * <div class="eyebrow">…status pill + spec + duration + browser…</div>
108
+ * <h1 class="what">…title with <em> emphasized inside…</h1>
109
+ * <pre class="error-message">…verbatim error stack trace…</pre>
110
+ * <div class="meta-strip">…6 small key-value items…</div>
111
+ * </section>
112
+ *
113
+ * The status pill keeps `class="status <status>"` so existing test assertions
114
+ * for "class=\"status failed\"" still match; the commit value still ships
115
+ * inside `<code>` and the buildUrl still becomes an `<a href="…">` for safe
116
+ * URLs only.
117
+ *
118
+ * `eventCount` is rendered when non-undefined; the caller (template.ts) passes
119
+ * `events.length` after `pruneToSizeBudget` runs.
120
+ */
121
+ export function renderHero(meta, eventCount, capturedAt) {
122
+ // ---- Eyebrow row -------------------------------------------------------
123
+ // Status pill (always shown), then spec / duration / browser separated by
124
+ // thin dividers. Each piece is optional except the status.
125
+ const TRACELANE_MARK = `<svg class="tracelane-mark" xmlns="http://www.w3.org/2000/svg" viewBox="36 96 184 64" height="14" role="img" aria-label="tracelane" style="display:inline-block;vertical-align:middle;flex-shrink:0"><g fill="none" stroke="#C2563D" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"><rect x="40" y="100" width="176" height="56" rx="4"/><path d="M64 128L96 128"/><path d="M112 128L144 128"/><path d="M160 128L192 128"/></g><circle cx="208" cy="128" r="6" fill="#C2563D"/></svg>`;
126
+ // The brand mark is NOT part of the separator-joined bits — joining it would
127
+ // render a stray "/" between the logo and the status pill (audit A-11). It is
128
+ // prepended verbatim; the first visible "/" should be between status and spec.
129
+ const eyebrowBits = [
130
+ `<span class="dot" aria-hidden="true"></span><span class="status ${escapeHtml(meta.status)}">test ${escapeHtml(statusVerb(meta.status))}</span>`,
131
+ ];
79
132
  if (meta.spec)
80
- rows.push(row('Spec', escapeHtml(meta.spec)));
133
+ eyebrowBits.push(`<span>${escapeHtml(meta.spec)}</span>`);
81
134
  if (meta.durationMs !== undefined)
82
- rows.push(row('Duration', escapeHtml(formatDuration(meta.durationMs))));
135
+ eyebrowBits.push(`<span>${escapeHtml(formatDuration(meta.durationMs))}</span>`);
83
136
  const browser = [meta.browserName, meta.browserVersion].filter(Boolean).join(' ');
84
- if (browser)
85
- rows.push(row('Browser', escapeHtml(browser)));
86
- if (meta.viewport) {
87
- rows.push(row('Viewport', escapeHtml(`${meta.viewport.width} × ${meta.viewport.height}`)));
137
+ if (browser || meta.viewport) {
138
+ const browserBits = [
139
+ browser,
140
+ meta.viewport ? `${meta.viewport.width}×${meta.viewport.height}` : '',
141
+ ]
142
+ .filter(Boolean)
143
+ .join(' · ');
144
+ eyebrowBits.push(`<span>${escapeHtml(browserBits)}</span>`);
88
145
  }
146
+ const eyebrow = `<div class="eyebrow">${TRACELANE_MARK}${eyebrowBits.join('<span class="sep" aria-hidden="true">/</span>')}</div>`;
147
+ // ---- Headline ----------------------------------------------------------
148
+ // Format: "<test title> — <emphasized status verb>." Always one sentence; the
149
+ // emphasized clause is the colour-of-the-failure-state moment.
150
+ const headline = `<h1 class="what">${escapeHtml(meta.title)} <em>${escapeHtml(statusVerb(meta.status))}</em>.</h1>`;
151
+ // ---- Error block (when present) ---------------------------------------
152
+ const errorBlock = meta.error ? `<pre class="error-message">${escapeHtml(meta.error)}</pre>` : '';
153
+ // ---- Meta strip --------------------------------------------------------
154
+ const stripItems = [];
155
+ if (meta.spec)
156
+ stripItems.push(stripItem('Spec', escapeHtml(meta.spec)));
157
+ if (meta.durationMs !== undefined)
158
+ stripItems.push(stripItem('Duration', escapeHtml(formatDuration(meta.durationMs))));
89
159
  if (meta.commitSha)
90
- rows.push(row('Commit', `<code>${escapeHtml(meta.commitSha)}</code>`));
160
+ stripItems.push(stripItem('Commit', `<code>${escapeHtml(meta.commitSha)}</code>`));
91
161
  if (meta.buildUrl) {
92
- const escaped = escapeHtml(meta.buildUrl);
93
- // Only render a clickable link for http(s); a non-http(s) URL (e.g. a
94
- // crafted `javascript:`) is shown as escaped text with no href.
95
- const value = isSafeUrl(meta.buildUrl) ? `<a href="${escaped}">${escaped}</a>` : escaped;
96
- rows.push(row('Build', value));
162
+ const escapedHref = escapeHtml(meta.buildUrl);
163
+ const value = isSafeUrl(meta.buildUrl)
164
+ ? `<a href="${escapedHref}">${escapedHref}</a>`
165
+ : escapedHref;
166
+ stripItems.push(stripItem('Build', value));
167
+ }
168
+ const capturedDate = capturedAt ?? new Date();
169
+ stripItems.push(stripItem('Captured', escapeHtml(formatCapturedAt(capturedDate))));
170
+ if (eventCount !== undefined) {
171
+ stripItems.push(stripItem('Events', escapeHtml(eventCount.toLocaleString('en-US'))));
97
172
  }
98
- const error = meta.error ? `<div class="error">${escapeHtml(meta.error)}</div>` : '';
99
- return `<header class="meta">
100
- <h1>${escapeHtml(meta.title)} <span class="status ${escapeHtml(meta.status)}">${escapeHtml(meta.status)}</span></h1>
101
- ${rows.length ? `<dl>${rows.join('')}</dl>` : ''}
102
- ${error}
103
- </header>`;
173
+ const strip = stripItems.length ? `<div class="meta-strip">${stripItems.join('')}</div>` : '';
174
+ return `<section class="hero">${eyebrow}${headline}${errorBlock}${strip}</section>`;
104
175
  }
105
176
  //# sourceMappingURL=metadata.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
package/dist/panels.d.ts CHANGED
@@ -14,19 +14,54 @@ export interface NetworkEntry {
14
14
  }
15
15
  /** rrweb console plugin tag (P1 PRD §F.3). */
16
16
  export declare const CONSOLE_PLUGIN = "rrweb/console@1";
17
+ /**
18
+ * rrweb network plugin tag — the framework-agnostic in-page capture
19
+ * (`rrweb/network@1`). Re-exported from `@cubenest/rrweb-core` so it stays
20
+ * in sync with the substrate's wire-format contract.
21
+ */
22
+ export declare const NETWORK_PLUGIN: "rrweb/network@1";
17
23
  /** Custom-event tag for the v1.1 rich network path (P1 PRD §E.3). */
18
24
  export declare const NETWORK_EVENT_TAG = "tracelane.test.network-error";
19
25
  /** console.error prefix for the v1 network fallback (P1 PRD §E.2). */
20
26
  export declare const NETWORK_CONSOLE_PREFIX = "[tracelane.net]";
21
27
  /**
22
- * Extract console rows: EventType.Plugin events emitted by the rrweb console
23
- * plugin. The plugin nests the level + serialized args under `data.payload`.
28
+ * console.error prefix the capture layer uses for privacy-safe response
29
+ * metadata consumed by `@tracelane/security`. Like the network-scrape lines,
30
+ * these are a non-console signal and are filtered OUT of the console panel —
31
+ * the security analyzer surfaces them as advisory findings instead. Defined
32
+ * locally (mirroring {@link NETWORK_CONSOLE_PREFIX}) rather than imported from
33
+ * `@tracelane/security` just for a string constant.
34
+ */
35
+ export declare const SEC_CONSOLE_PREFIX = "[tracelane.sec]";
36
+ /**
37
+ * Extract console panel rows. Drops the CDP network-scrape lines
38
+ * ('[tracelane.net] …'): they are a *network* signal that `extractNetwork`
39
+ * already surfaces as structured rows in the Network panel. Letting them
40
+ * through here double-renders the same failure as a raw console string,
41
+ * inconsistently with the structured row (audit A-4). Also drops the
42
+ * '[tracelane.sec] …' response-metadata lines: those are a *security* signal
43
+ * the analyzer turns into advisory findings, not console output (Task 9).
24
44
  */
25
45
  export declare function extractConsole(events: readonly eventWithTime[]): ConsoleEntry[];
26
46
  /**
27
- * Extract network-error rows. Prefers the v1.1 custom-event path
28
- * (EventType.Custom, tag 'tracelane.test.network-error'); when none are present,
29
- * falls back to scraping console.error lines prefixed '[tracelane.net]' (v1).
47
+ * Extract network-error rows.
48
+ *
49
+ * The in-page rrweb network plugin (`rrweb/network@1`, the Phase 5 default)
50
+ * captures via PerformanceObserver, so its rows are status-poor for
51
+ * cross-origin requests. The legacy CDP `[tracelane.net]` console-scrape, when
52
+ * present, carries the AUTHORITATIVE HTTP status. So rather than "first
53
+ * non-empty source wins" — which would shadow the authoritative CDP rows
54
+ * whenever the plugin emitted anything (audit A-4) — we UNION the plugin + CDP
55
+ * sources, with CDP rows replacing an overlapping plugin row for the same URL.
56
+ *
57
+ * Resolution:
58
+ * 1. Failed rows from the in-page network plugin (EventType.Plugin) merged
59
+ * with the v1 CDP console-scrape ('[tracelane.net]'), where a CDP row
60
+ * REPLACES an overlapping plugin row for the same request (real status
61
+ * wins over a PerformanceObserver 0). Output ordered by timestamp.
62
+ * 2. If neither produced any rows, fall back to the v1.1 custom-event path
63
+ * (EventType.Custom) — pre-Phase-5 recorders that used neither the plugin
64
+ * nor the CDP console-scrape.
30
65
  */
31
66
  export declare function extractNetwork(events: readonly eventWithTime[]): NetworkEntry[];
32
67
  //# sourceMappingURL=panels.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../src/panels.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,2BAA2B;AAC3B,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,iCAAiC;AACjC,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,8CAA8C;AAC9C,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAChD,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,iCAAiC,CAAC;AAChE,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AAkDxD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,YAAY,EAAE,CAW/E;AAkBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,YAAY,EAAE,CA2B/E"}
1
+ {"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../src/panels.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAuC,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE/F,2BAA2B;AAC3B,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,iCAAiC;AACjC,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,8CAA8C;AAC9C,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAChD;;;;GAIG;AACH,eAAO,MAAM,cAAc,mBAAsB,CAAC;AAClD,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,iCAAiC,CAAC;AAChE,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AACxD;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AA+EpD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,YAAY,EAAE,CAK/E;AAkGD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,YAAY,EAAE,CAmD/E"}