@setsquare/review-sdk 0.0.1

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 (181) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +57 -0
  3. package/README.md +338 -0
  4. package/THIRD-PARTY-NOTICES.md +61 -0
  5. package/dist/autoscan.d.ts +25 -0
  6. package/dist/autoscan.d.ts.map +1 -0
  7. package/dist/autoscan.js +332 -0
  8. package/dist/autoscan.js.map +1 -0
  9. package/dist/axe.d.ts +96 -0
  10. package/dist/axe.d.ts.map +1 -0
  11. package/dist/axe.js +210 -0
  12. package/dist/axe.js.map +1 -0
  13. package/dist/bin/setsquare.d.ts +3 -0
  14. package/dist/bin/setsquare.d.ts.map +1 -0
  15. package/dist/bin/setsquare.js +21 -0
  16. package/dist/bin/setsquare.js.map +1 -0
  17. package/dist/brand.d.ts +84 -0
  18. package/dist/brand.d.ts.map +1 -0
  19. package/dist/brand.js +335 -0
  20. package/dist/brand.js.map +1 -0
  21. package/dist/checks/dynamic.d.ts +57 -0
  22. package/dist/checks/dynamic.d.ts.map +1 -0
  23. package/dist/checks/dynamic.js +184 -0
  24. package/dist/checks/dynamic.js.map +1 -0
  25. package/dist/checks/rule-pack.d.ts +34 -0
  26. package/dist/checks/rule-pack.d.ts.map +1 -0
  27. package/dist/checks/rule-pack.js +270 -0
  28. package/dist/checks/rule-pack.js.map +1 -0
  29. package/dist/checks/versions.d.ts +28 -0
  30. package/dist/checks/versions.d.ts.map +1 -0
  31. package/dist/checks/versions.js +45 -0
  32. package/dist/checks/versions.js.map +1 -0
  33. package/dist/ci.d.ts +37 -0
  34. package/dist/ci.d.ts.map +1 -0
  35. package/dist/ci.js +199 -0
  36. package/dist/ci.js.map +1 -0
  37. package/dist/contract.d.ts +334 -0
  38. package/dist/contract.d.ts.map +1 -0
  39. package/dist/contract.js +35 -0
  40. package/dist/contract.js.map +1 -0
  41. package/dist/dedupe.d.ts +79 -0
  42. package/dist/dedupe.d.ts.map +1 -0
  43. package/dist/dedupe.js +102 -0
  44. package/dist/dedupe.js.map +1 -0
  45. package/dist/document.d.ts +29 -0
  46. package/dist/document.d.ts.map +1 -0
  47. package/dist/document.js +94 -0
  48. package/dist/document.js.map +1 -0
  49. package/dist/envelope.d.ts +124 -0
  50. package/dist/envelope.d.ts.map +1 -0
  51. package/dist/envelope.js +337 -0
  52. package/dist/envelope.js.map +1 -0
  53. package/dist/escape.d.ts +14 -0
  54. package/dist/escape.d.ts.map +1 -0
  55. package/dist/escape.js +20 -0
  56. package/dist/escape.js.map +1 -0
  57. package/dist/findings.d.ts +47 -0
  58. package/dist/findings.d.ts.map +1 -0
  59. package/dist/findings.js +229 -0
  60. package/dist/findings.js.map +1 -0
  61. package/dist/fixture.d.ts +7 -0
  62. package/dist/fixture.d.ts.map +1 -0
  63. package/dist/fixture.js +237 -0
  64. package/dist/fixture.js.map +1 -0
  65. package/dist/group.d.ts +214 -0
  66. package/dist/group.d.ts.map +1 -0
  67. package/dist/group.js +709 -0
  68. package/dist/group.js.map +1 -0
  69. package/dist/html-report.d.ts +68 -0
  70. package/dist/html-report.d.ts.map +1 -0
  71. package/dist/html-report.js +649 -0
  72. package/dist/html-report.js.map +1 -0
  73. package/dist/human.d.ts +65 -0
  74. package/dist/human.d.ts.map +1 -0
  75. package/dist/human.js +111 -0
  76. package/dist/human.js.map +1 -0
  77. package/dist/index.d.ts +34 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +33 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/infer.d.ts +65 -0
  82. package/dist/infer.d.ts.map +1 -0
  83. package/dist/infer.js +67 -0
  84. package/dist/infer.js.map +1 -0
  85. package/dist/insights.d.ts +140 -0
  86. package/dist/insights.d.ts.map +1 -0
  87. package/dist/insights.js +483 -0
  88. package/dist/insights.js.map +1 -0
  89. package/dist/install.d.ts +8 -0
  90. package/dist/install.d.ts.map +1 -0
  91. package/dist/install.js +114 -0
  92. package/dist/install.js.map +1 -0
  93. package/dist/links.d.ts +45 -0
  94. package/dist/links.d.ts.map +1 -0
  95. package/dist/links.js +45 -0
  96. package/dist/links.js.map +1 -0
  97. package/dist/mask.d.ts +85 -0
  98. package/dist/mask.d.ts.map +1 -0
  99. package/dist/mask.js +98 -0
  100. package/dist/mask.js.map +1 -0
  101. package/dist/observe.d.ts +51 -0
  102. package/dist/observe.d.ts.map +1 -0
  103. package/dist/observe.js +233 -0
  104. package/dist/observe.js.map +1 -0
  105. package/dist/options.d.ts +249 -0
  106. package/dist/options.d.ts.map +1 -0
  107. package/dist/options.js +185 -0
  108. package/dist/options.js.map +1 -0
  109. package/dist/output.d.ts +113 -0
  110. package/dist/output.d.ts.map +1 -0
  111. package/dist/output.js +231 -0
  112. package/dist/output.js.map +1 -0
  113. package/dist/perf.d.ts +11 -0
  114. package/dist/perf.d.ts.map +1 -0
  115. package/dist/perf.js +150 -0
  116. package/dist/perf.js.map +1 -0
  117. package/dist/reading-level.d.ts +73 -0
  118. package/dist/reading-level.d.ts.map +1 -0
  119. package/dist/reading-level.js +189 -0
  120. package/dist/reading-level.js.map +1 -0
  121. package/dist/reporter.d.ts +94 -0
  122. package/dist/reporter.d.ts.map +1 -0
  123. package/dist/reporter.js +709 -0
  124. package/dist/reporter.js.map +1 -0
  125. package/dist/rules.d.ts +55 -0
  126. package/dist/rules.d.ts.map +1 -0
  127. package/dist/rules.js +77 -0
  128. package/dist/rules.js.map +1 -0
  129. package/dist/runtime.d.ts +32 -0
  130. package/dist/runtime.d.ts.map +1 -0
  131. package/dist/runtime.js +67 -0
  132. package/dist/runtime.js.map +1 -0
  133. package/dist/sanitise.d.ts +116 -0
  134. package/dist/sanitise.d.ts.map +1 -0
  135. package/dist/sanitise.js +247 -0
  136. package/dist/sanitise.js.map +1 -0
  137. package/dist/scan.d.ts +60 -0
  138. package/dist/scan.d.ts.map +1 -0
  139. package/dist/scan.js +246 -0
  140. package/dist/scan.js.map +1 -0
  141. package/dist/screens.d.ts +98 -0
  142. package/dist/screens.d.ts.map +1 -0
  143. package/dist/screens.js +301 -0
  144. package/dist/screens.js.map +1 -0
  145. package/dist/settle.d.ts +65 -0
  146. package/dist/settle.d.ts.map +1 -0
  147. package/dist/settle.js +162 -0
  148. package/dist/settle.js.map +1 -0
  149. package/dist/shots.d.ts +109 -0
  150. package/dist/shots.d.ts.map +1 -0
  151. package/dist/shots.js +113 -0
  152. package/dist/shots.js.map +1 -0
  153. package/dist/style.d.ts +47 -0
  154. package/dist/style.d.ts.map +1 -0
  155. package/dist/style.js +154 -0
  156. package/dist/style.js.map +1 -0
  157. package/dist/suite.d.ts +218 -0
  158. package/dist/suite.d.ts.map +1 -0
  159. package/dist/suite.js +219 -0
  160. package/dist/suite.js.map +1 -0
  161. package/dist/summary.d.ts +268 -0
  162. package/dist/summary.d.ts.map +1 -0
  163. package/dist/summary.js +1308 -0
  164. package/dist/summary.js.map +1 -0
  165. package/dist/unscannable.d.ts +75 -0
  166. package/dist/unscannable.d.ts.map +1 -0
  167. package/dist/unscannable.js +111 -0
  168. package/dist/unscannable.js.map +1 -0
  169. package/dist/versions.d.ts +13 -0
  170. package/dist/versions.d.ts.map +1 -0
  171. package/dist/versions.js +39 -0
  172. package/dist/versions.js.map +1 -0
  173. package/dist/wcag-map.d.ts +19 -0
  174. package/dist/wcag-map.d.ts.map +1 -0
  175. package/dist/wcag-map.js +52 -0
  176. package/dist/wcag-map.js.map +1 -0
  177. package/dist/with-setsquare.d.ts +26 -0
  178. package/dist/with-setsquare.d.ts.map +1 -0
  179. package/dist/with-setsquare.js +70 -0
  180. package/dist/with-setsquare.js.map +1 -0
  181. package/package.json +81 -0
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Every URL the SDK is allowed to know about, in one file.
3
+ *
4
+ * `boundaries.test.ts` forbids hardcoded URLs everywhere else in the shipped
5
+ * source and permits them only here. That is deliberately stricter than a blanket
6
+ * exemption: it means any future URL — a telemetry endpoint, a version check, an
7
+ * error reporter — has to be added to a file whose entire purpose is to be read
8
+ * during review, rather than appearing quietly inside a module nobody re-reads.
9
+ *
10
+ * None of these is ever REQUESTED. The SDK contains no network client and cannot
11
+ * fetch anything; these are strings printed for a human to click.
12
+ */
13
+ /** Printed once per run, in the closing block. Never fetched. */
14
+ export declare const PLATFORM_URL = "https://setsquare.dev";
15
+ /**
16
+ * Where a rule's remediation guidance lives.
17
+ *
18
+ * Currently Deque's own page, taken from axe's `helpUrl` — which makes it an
19
+ * SDK-computed fact rather than authored content, and keeps the free layer on
20
+ * the right side of its own boundary. Setsquare's fix-pattern library (P5)
21
+ * replaces this with our own pages when they exist, and the terminal will still
22
+ * only ever link: the guidance itself stays on the site, free to read, and
23
+ * in-context delivery is what the platform sells.
24
+ */
25
+ export declare function ruleHelpUrl(finding: {
26
+ helpUrl?: string;
27
+ }): string | undefined;
28
+ /**
29
+ * The W3C Understanding page for 3.1.5 Reading Level — the spec the
30
+ * `setsquare-reading-level` heuristic is implemented from, and where a person
31
+ * deciding the criterion should start. Printed and linked, never fetched.
32
+ */
33
+ export declare const READING_LEVEL_HELP_URL = "https://www.w3.org/WAI/WCAG22/Understanding/reading-level.html";
34
+ /**
35
+ * The Understanding pages for the criteria Setsquare's own rule pack
36
+ * implements — the specs the checks are written FROM (clean-room: axe's rule
37
+ * source is never opened), and where a person triaging a finding should start.
38
+ * Printed and linked, never fetched.
39
+ */
40
+ export declare const TARGET_SIZE_ENHANCED_HELP_URL = "https://www.w3.org/WAI/WCAG22/Understanding/target-size-enhanced.html";
41
+ export declare const VISUAL_PRESENTATION_HELP_URL = "https://www.w3.org/WAI/WCAG22/Understanding/visual-presentation.html";
42
+ export declare const LINK_PURPOSE_LINK_ONLY_HELP_URL = "https://www.w3.org/WAI/WCAG22/Understanding/link-purpose-link-only.html";
43
+ export declare const TEXT_SPACING_HELP_URL = "https://www.w3.org/WAI/WCAG22/Understanding/text-spacing.html";
44
+ export declare const STATUS_MESSAGES_HELP_URL = "https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html";
45
+ //# sourceMappingURL=links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,iEAAiE;AACjE,eAAO,MAAM,YAAY,0BAA0B,CAAC;AAEpD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAE7E;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,mEAC+B,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,0EAC+B,CAAC;AAC1E,eAAO,MAAM,4BAA4B,yEAC+B,CAAC;AACzE,eAAO,MAAM,+BAA+B,4EAC+B,CAAC;AAC5E,eAAO,MAAM,qBAAqB,kEAC+B,CAAC;AAClE,eAAO,MAAM,wBAAwB,qEAC+B,CAAC"}
package/dist/links.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Every URL the SDK is allowed to know about, in one file.
3
+ *
4
+ * `boundaries.test.ts` forbids hardcoded URLs everywhere else in the shipped
5
+ * source and permits them only here. That is deliberately stricter than a blanket
6
+ * exemption: it means any future URL — a telemetry endpoint, a version check, an
7
+ * error reporter — has to be added to a file whose entire purpose is to be read
8
+ * during review, rather than appearing quietly inside a module nobody re-reads.
9
+ *
10
+ * None of these is ever REQUESTED. The SDK contains no network client and cannot
11
+ * fetch anything; these are strings printed for a human to click.
12
+ */
13
+ /** Printed once per run, in the closing block. Never fetched. */
14
+ export const PLATFORM_URL = 'https://setsquare.dev';
15
+ /**
16
+ * Where a rule's remediation guidance lives.
17
+ *
18
+ * Currently Deque's own page, taken from axe's `helpUrl` — which makes it an
19
+ * SDK-computed fact rather than authored content, and keeps the free layer on
20
+ * the right side of its own boundary. Setsquare's fix-pattern library (P5)
21
+ * replaces this with our own pages when they exist, and the terminal will still
22
+ * only ever link: the guidance itself stays on the site, free to read, and
23
+ * in-context delivery is what the platform sells.
24
+ */
25
+ export function ruleHelpUrl(finding) {
26
+ return finding.helpUrl;
27
+ }
28
+ /**
29
+ * The W3C Understanding page for 3.1.5 Reading Level — the spec the
30
+ * `setsquare-reading-level` heuristic is implemented from, and where a person
31
+ * deciding the criterion should start. Printed and linked, never fetched.
32
+ */
33
+ export const READING_LEVEL_HELP_URL = 'https://www.w3.org/WAI/WCAG22/Understanding/reading-level.html';
34
+ /**
35
+ * The Understanding pages for the criteria Setsquare's own rule pack
36
+ * implements — the specs the checks are written FROM (clean-room: axe's rule
37
+ * source is never opened), and where a person triaging a finding should start.
38
+ * Printed and linked, never fetched.
39
+ */
40
+ export const TARGET_SIZE_ENHANCED_HELP_URL = 'https://www.w3.org/WAI/WCAG22/Understanding/target-size-enhanced.html';
41
+ export const VISUAL_PRESENTATION_HELP_URL = 'https://www.w3.org/WAI/WCAG22/Understanding/visual-presentation.html';
42
+ export const LINK_PURPOSE_LINK_ONLY_HELP_URL = 'https://www.w3.org/WAI/WCAG22/Understanding/link-purpose-link-only.html';
43
+ export const TEXT_SPACING_HELP_URL = 'https://www.w3.org/WAI/WCAG22/Understanding/text-spacing.html';
44
+ export const STATUS_MESSAGES_HELP_URL = 'https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html';
45
+ //# sourceMappingURL=links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"links.js","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,iEAAiE;AACjE,MAAM,CAAC,MAAM,YAAY,GAAG,uBAAuB,CAAC;AAEpD;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,OAA6B;IACvD,OAAO,OAAO,CAAC,OAAO,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GACjC,gEAAgE,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,6BAA6B,GACxC,uEAAuE,CAAC;AAC1E,MAAM,CAAC,MAAM,4BAA4B,GACvC,sEAAsE,CAAC;AACzE,MAAM,CAAC,MAAM,+BAA+B,GAC1C,yEAAyE,CAAC;AAC5E,MAAM,CAAC,MAAM,qBAAqB,GAChC,+DAA+D,CAAC;AAClE,MAAM,CAAC,MAAM,wBAAwB,GACnC,kEAAkE,CAAC"}
package/dist/mask.d.ts ADDED
@@ -0,0 +1,85 @@
1
+ import type { Locator, Page } from '@playwright/test';
2
+ /**
3
+ * Masking: deciding what must never be visible in a screenshot.
4
+ *
5
+ * Note what this file does NOT do — it takes no screenshots, and the SDK
6
+ * contains no code that does. That is the free-layer boundary as a structural
7
+ * property rather than a setting: visual evidence is a platform capability, so
8
+ * the local path holds no pixels at all, and there is no capture path to
9
+ * accidentally leave switched on. `boundaries.test.ts` asserts that no shipped
10
+ * source file so much as names an image format.
11
+ *
12
+ * What exists here is the part that has to be right BEFORE any bytes are ever
13
+ * captured: which regions are covered. Playwright masks at capture time — it
14
+ * paints over the region before the image exists — so a screenshot taken with
15
+ * these locators never contains the pixels at all. That is meaningfully
16
+ * different from blurring afterwards, where the original existed, however
17
+ * briefly, and may sit in a trace or a temp file.
18
+ *
19
+ * The composition is proven against a real page in
20
+ * `fixtures/specs/anonymous/masking.spec.ts`, which is also the only place in the
21
+ * repo that takes a screenshot — into memory, never to disk.
22
+ */
23
+ /**
24
+ * Selectors masked unless a customer opts out.
25
+ *
26
+ * Chosen to be defensible rather than exhaustive, because both errors are real:
27
+ * masking too little puts a candidate's email in an evidence artifact, and
28
+ * masking too much produces a screenshot of grey boxes that proves nothing about
29
+ * accessibility.
30
+ *
31
+ * The rule applied: mask fields whose CONTENT is personal by definition, and
32
+ * leave everything else to configuration. A `<div>` holding a name is
33
+ * indistinguishable from a `<div>` holding a job title, so it is not guessed at.
34
+ */
35
+ export declare const DEFAULT_MASK_SELECTORS: readonly ["[data-setsquare-mask]", "input[type=\"password\"]", "input[type=\"email\"]", "input[type=\"tel\"]", "[autocomplete*=\"cc-\"]", "[autocomplete=\"email\"]", "[autocomplete=\"tel\"]", "[autocomplete*=\"name\"]", "[autocomplete=\"street-address\"]", "[autocomplete=\"postal-code\"]", "[autocomplete=\"bday\"]"];
36
+ export interface MaskConfig {
37
+ /** Extra selectors, composed WITH the defaults rather than replacing them. */
38
+ mask?: string[];
39
+ /**
40
+ * Drop the built-in defaults.
41
+ *
42
+ * Available because a customer's page may legitimately use these attributes on
43
+ * non-personal fields, and being unable to correct us would make the feature
44
+ * unusable. Turning them off is a deliberate, documented act — which is the
45
+ * standard the upload defaults are held to as well.
46
+ */
47
+ maskDefaults?: boolean;
48
+ }
49
+ /**
50
+ * The full selector list, defaults first.
51
+ *
52
+ * Deduplicated, because a customer repeating a default should not produce two
53
+ * identical locators and twice the work; ordered deterministically so two runs
54
+ * of the same configuration mask identically.
55
+ */
56
+ export declare function maskSelectors(config?: MaskConfig): string[];
57
+ /**
58
+ * Resolve the selectors to locators for `page.screenshot({ mask })`.
59
+ *
60
+ * Deliberately returns locators rather than taking the screenshot itself. The
61
+ * SDK's job here is to know WHAT to cover; the platform slice that eventually
62
+ * captures and uploads is what will call this. Keeping the two apart is what lets
63
+ * the local path be structurally incapable of producing an image rather than
64
+ * merely configured not to.
65
+ */
66
+ export declare function maskLocators(page: Page, config?: MaskConfig): Locator[];
67
+ /**
68
+ * Upload defaults, locked.
69
+ *
70
+ * Not a suggestion and not a starting point: these are the values the product's
71
+ * data-protection posture is built on, and changing any of them is an explicit,
72
+ * documented act by the customer rather than something that drifts.
73
+ *
74
+ * `traces: 'off'` is the strictest of the three and the least negotiable. A
75
+ * Playwright trace contains full DOM snapshots, network payloads and screenshots
76
+ * of every step — it is the richest possible source of exactly the data
77
+ * sanitisation and masking exist to keep out.
78
+ */
79
+ export declare const UPLOAD_DEFAULTS: {
80
+ readonly screenshots: "masked-only";
81
+ readonly traces: "off";
82
+ readonly htmlSnippets: "strip";
83
+ };
84
+ export type UploadDefaults = typeof UPLOAD_DEFAULTS;
85
+ //# sourceMappingURL=mask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.d.ts","sourceRoot":"","sources":["../src/mask.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,+TAwBzB,CAAC;AAEX,MAAM,WAAW,UAAU;IACzB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,UAAe,GAAG,MAAM,EAAE,CAM/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,GAAE,UAAe,GAAG,OAAO,EAAE,CAE3E;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,OAAO,eAAe,CAAC"}
package/dist/mask.js ADDED
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Masking: deciding what must never be visible in a screenshot.
3
+ *
4
+ * Note what this file does NOT do — it takes no screenshots, and the SDK
5
+ * contains no code that does. That is the free-layer boundary as a structural
6
+ * property rather than a setting: visual evidence is a platform capability, so
7
+ * the local path holds no pixels at all, and there is no capture path to
8
+ * accidentally leave switched on. `boundaries.test.ts` asserts that no shipped
9
+ * source file so much as names an image format.
10
+ *
11
+ * What exists here is the part that has to be right BEFORE any bytes are ever
12
+ * captured: which regions are covered. Playwright masks at capture time — it
13
+ * paints over the region before the image exists — so a screenshot taken with
14
+ * these locators never contains the pixels at all. That is meaningfully
15
+ * different from blurring afterwards, where the original existed, however
16
+ * briefly, and may sit in a trace or a temp file.
17
+ *
18
+ * The composition is proven against a real page in
19
+ * `fixtures/specs/anonymous/masking.spec.ts`, which is also the only place in the
20
+ * repo that takes a screenshot — into memory, never to disk.
21
+ */
22
+ /**
23
+ * Selectors masked unless a customer opts out.
24
+ *
25
+ * Chosen to be defensible rather than exhaustive, because both errors are real:
26
+ * masking too little puts a candidate's email in an evidence artifact, and
27
+ * masking too much produces a screenshot of grey boxes that proves nothing about
28
+ * accessibility.
29
+ *
30
+ * The rule applied: mask fields whose CONTENT is personal by definition, and
31
+ * leave everything else to configuration. A `<div>` holding a name is
32
+ * indistinguishable from a `<div>` holding a job title, so it is not guessed at.
33
+ */
34
+ export const DEFAULT_MASK_SELECTORS = [
35
+ /*
36
+ * The explicit opt-in, first. A customer who has marked something is telling us
37
+ * about their own data model, which nothing here can infer.
38
+ */
39
+ '[data-setsquare-mask]',
40
+ // Input types whose content is personal by definition.
41
+ 'input[type="password"]',
42
+ 'input[type="email"]',
43
+ 'input[type="tel"]',
44
+ /*
45
+ * Autocomplete tokens — the standard vocabulary browsers already use to
46
+ * identify personal fields, which makes it the closest thing to a declared
47
+ * schema for PII that exists on the open web.
48
+ */
49
+ '[autocomplete*="cc-"]',
50
+ '[autocomplete="email"]',
51
+ '[autocomplete="tel"]',
52
+ '[autocomplete*="name"]',
53
+ '[autocomplete="street-address"]',
54
+ '[autocomplete="postal-code"]',
55
+ '[autocomplete="bday"]',
56
+ ];
57
+ /**
58
+ * The full selector list, defaults first.
59
+ *
60
+ * Deduplicated, because a customer repeating a default should not produce two
61
+ * identical locators and twice the work; ordered deterministically so two runs
62
+ * of the same configuration mask identically.
63
+ */
64
+ export function maskSelectors(config = {}) {
65
+ const useDefaults = config.maskDefaults ?? true;
66
+ const selectors = [...(useDefaults ? DEFAULT_MASK_SELECTORS : []), ...(config.mask ?? [])];
67
+ return [...new Set(selectors.filter((selector) => selector.trim().length > 0))];
68
+ }
69
+ /**
70
+ * Resolve the selectors to locators for `page.screenshot({ mask })`.
71
+ *
72
+ * Deliberately returns locators rather than taking the screenshot itself. The
73
+ * SDK's job here is to know WHAT to cover; the platform slice that eventually
74
+ * captures and uploads is what will call this. Keeping the two apart is what lets
75
+ * the local path be structurally incapable of producing an image rather than
76
+ * merely configured not to.
77
+ */
78
+ export function maskLocators(page, config = {}) {
79
+ return maskSelectors(config).map((selector) => page.locator(selector));
80
+ }
81
+ /**
82
+ * Upload defaults, locked.
83
+ *
84
+ * Not a suggestion and not a starting point: these are the values the product's
85
+ * data-protection posture is built on, and changing any of them is an explicit,
86
+ * documented act by the customer rather than something that drifts.
87
+ *
88
+ * `traces: 'off'` is the strictest of the three and the least negotiable. A
89
+ * Playwright trace contains full DOM snapshots, network payloads and screenshots
90
+ * of every step — it is the richest possible source of exactly the data
91
+ * sanitisation and masking exist to keep out.
92
+ */
93
+ export const UPLOAD_DEFAULTS = {
94
+ screenshots: 'masked-only',
95
+ traces: 'off',
96
+ htmlSnippets: 'strip',
97
+ };
98
+ //# sourceMappingURL=mask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.js","sourceRoot":"","sources":["../src/mask.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC;;;OAGG;IACH,uBAAuB;IAEvB,uDAAuD;IACvD,wBAAwB;IACxB,qBAAqB;IACrB,mBAAmB;IAEnB;;;;OAIG;IACH,uBAAuB;IACvB,wBAAwB;IACxB,sBAAsB;IACtB,wBAAwB;IACxB,iCAAiC;IACjC,8BAA8B;IAC9B,uBAAuB;CACf,CAAC;AAgBX;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,SAAqB,EAAE;IACnD,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC;IAEhD,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;IAE3F,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU,EAAE,SAAqB,EAAE;IAC9D,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;AACzE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,WAAW,EAAE,aAAa;IAC1B,MAAM,EAAE,KAAK;IACb,YAAY,EAAE,OAAO;CACb,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type { Page } from '@playwright/test';
2
+ import type { PageRuntime, PageRuntimeEvent, PageRuntimeKind } from '@setsquare/schema';
3
+ /**
4
+ * A bounded per-page accumulator.
5
+ *
6
+ * Deliberately not a class with a `toJSON`: the reporter never sees this object,
7
+ * only the plain `PageRuntime` that `snapshot()` returns.
8
+ */
9
+ export declare class PageRuntimeAccumulator {
10
+ private readonly startedAt;
11
+ private readonly counts;
12
+ private readonly distinct;
13
+ private omitted;
14
+ constructor(startedAt: number);
15
+ /**
16
+ * Record one event.
17
+ *
18
+ * `key` is what makes two events "the same" for exemplar purposes — the same
19
+ * error thrown a thousand times is one thing that is wrong, not a thousand.
20
+ */
21
+ add(kind: PageRuntimeKind, key: string, event: () => Omit<PageRuntimeEvent, 'kind' | 'atMs'>): void;
22
+ /**
23
+ * The wire shape. **Always a block, never `undefined`.**
24
+ *
25
+ * A clean page returns `{ observed: [...6 kinds], counts: {} }`, and that is
26
+ * the entire point rather than wasted bytes: it is the difference between "we
27
+ * listened and saw none" and "we did not look". The second is expressed by the
28
+ * scan carrying no `runtime` at all — which happens when this is not the first
29
+ * scan of a page load, or when the envelope predates the capability.
30
+ *
31
+ * A bare `consoleErrors: 0` could express neither, which is why no such field
32
+ * exists. Same rule `perf.ts` follows for CLS on engines that cannot measure it.
33
+ */
34
+ snapshot(): PageRuntime;
35
+ }
36
+ /**
37
+ * This page's runtime block, or `undefined` if the page was never observed.
38
+ *
39
+ * Callers gate this the way `perf` is gated — first scan of a `visitRef` only —
40
+ * because these are facts about a page LOAD, not about a scan. Scanning one page
41
+ * in four states must not report its console errors four times.
42
+ */
43
+ export declare function pageRuntime(page: Page): PageRuntime | undefined;
44
+ /**
45
+ * Attach the runtime listeners to one page.
46
+ *
47
+ * Never throws: an engine that refuses a listener must cost the customer nothing,
48
+ * and partial evidence beats none provided we do not pretend it is complete.
49
+ */
50
+ export declare function observePageRuntime(page: Page, startedAt: number): void;
51
+ //# sourceMappingURL=observe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../src/observe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,IAAI,EAAqB,MAAM,kBAAkB,CAAC;AAChF,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAmFxF;;;;;GAKG;AACH,qBAAa,sBAAsB;IAKrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAChE,OAAO,CAAC,OAAO,CAAK;gBAES,SAAS,EAAE,MAAM;IAE9C;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC;IAmB5F;;;;;;;;;;;OAWG;IACH,QAAQ,IAAI,WAAW;CAWxB;AAkCD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,SAAS,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CA8DtE"}
@@ -0,0 +1,233 @@
1
+ import { MAX_DISTINCT_RUNTIME_EVENTS, MAX_RUNTIME_EXEMPLARS, MAX_RUNTIME_MESSAGE_LENGTH, } from '@setsquare/schema/limits';
2
+ import { capLength, stripHostileCharacters, toUrlPattern } from './sanitise.js';
3
+ /**
4
+ * What the page itself did while we were on it.
5
+ *
6
+ * The SDK already holds the richest object in the run — a live `BrowserContext` —
7
+ * and until now read one event off it. Everything here is on that object, costs
8
+ * approximately nothing, and is aggregated nowhere in Playwright's own report:
9
+ * a 500 on a background XHR during fourteen passing tests fails no assertion and
10
+ * appears in no artefact.
11
+ *
12
+ * ---------------------------------------------------------------------------
13
+ * THIS CODE RUNS IN A CUSTOMER'S TEST PROCESS, ON EVERY PAGE. Three constraints
14
+ * follow, and none of them is negotiable:
15
+ *
16
+ * 1. `response` fires for EVERY response. A media-heavy page is 300–800 of them,
17
+ * times the tests, times the engines — six figures of events in a run. So the
18
+ * handler is fully synchronous, reads only synchronous getters, and returns on
19
+ * its first line for the overwhelmingly common case (`status < 400`), which
20
+ * means the common path allocates nothing at all.
21
+ *
22
+ * 2. It must NEVER read a response body. `response.text()` / `.body()` / `.json()`
23
+ * buffer the payload and can deadlock a page whose request is still streaming
24
+ * — turning an observer into the cause of a customer's timeout. A grep
25
+ * assertion in `observe.test.ts` enforces this, because the failure would be
26
+ * intermittent and would be blamed on their app.
27
+ *
28
+ * 3. Memory is counters plus a bounded exemplar set, never a log. A page throwing
29
+ * inside `requestAnimationFrame` emits without limit for the length of the
30
+ * test; uncapped, the map grows with it. Worst case at the current caps is
31
+ * roughly 15 KB per page (50 distinct keys, 20 exemplars at the message cap).
32
+ * ---------------------------------------------------------------------------
33
+ *
34
+ * The listeners attach per page, from the context fixture's existing `observe`,
35
+ * which keeps the measured `context`-over-`page` fixture win intact: a test that
36
+ * never opens a browser opens no page and therefore pays nothing.
37
+ *
38
+ * Sanitisation happens here rather than in the reporter, for the reason
39
+ * `contract.ts` gives — an attachment is also written into Playwright's own HTML
40
+ * report and trace, so a hostile console message must be bounded before it leaves
41
+ * the worker, not after.
42
+ */
43
+ /**
44
+ * Which categories we attach listeners for.
45
+ *
46
+ * Playwright normalises `console`, `pageerror`, `requestfailed` and `response`
47
+ * across all three engines at the API level, so the listeners themselves are
48
+ * portable. The CONTENT is not, as the cross-engine lane
49
+ * (`fixtures/playwright.engines.config.ts`) measured: on the same page Chromium
50
+ * and WebKit report 123 console errors and Firefox 121, because the first two also
51
+ * log a failed-resource error and Firefox does not. So a count is a fact about one
52
+ * engine's console and must never be summed or compared across them.
53
+ *
54
+ * `request.failure()?.errorText` is likewise engine-specific
55
+ * (`net::ERR_BLOCKED_BY_CSP` in Chromium, other wording in Gecko and WebKit).
56
+ * Hence the rule this module follows and the schema documents: carry `errorText`
57
+ * verbatim, never classify a cause from message text. A `blocked-by-csp`
58
+ * category derived from prose would read as computed while being guessed.
59
+ *
60
+ * Worth recording honestly: `pageerror` message wording happened to AGREE on all
61
+ * three for the fixture's two errors. That is not a guarantee — V8, SpiderMonkey
62
+ * and JSC merely phrase those particular two the same way — and it is why nothing
63
+ * is parsed out of a message even though it would have worked on that fixture.
64
+ */
65
+ const OBSERVED_KINDS = [
66
+ 'console-error',
67
+ 'console-warning',
68
+ 'page-error',
69
+ 'request-failed',
70
+ 'response-4xx',
71
+ 'response-5xx',
72
+ ];
73
+ /**
74
+ * A bounded per-page accumulator.
75
+ *
76
+ * Deliberately not a class with a `toJSON`: the reporter never sees this object,
77
+ * only the plain `PageRuntime` that `snapshot()` returns.
78
+ */
79
+ export class PageRuntimeAccumulator {
80
+ startedAt;
81
+ counts = {};
82
+ distinct = new Map();
83
+ omitted = 0;
84
+ constructor(startedAt) {
85
+ this.startedAt = startedAt;
86
+ }
87
+ /**
88
+ * Record one event.
89
+ *
90
+ * `key` is what makes two events "the same" for exemplar purposes — the same
91
+ * error thrown a thousand times is one thing that is wrong, not a thousand.
92
+ */
93
+ add(kind, key, event) {
94
+ this.counts[kind] = (this.counts[kind] ?? 0) + 1;
95
+ if (this.distinct.has(key))
96
+ return;
97
+ if (this.distinct.size >= MAX_DISTINCT_RUNTIME_EVENTS) {
98
+ this.omitted += 1;
99
+ return;
100
+ }
101
+ // The event body is built lazily, so a repeat of something already seen — the
102
+ // common case on a noisy page — costs one map lookup and an integer bump.
103
+ this.distinct.set(key, {
104
+ kind,
105
+ ...event(),
106
+ atMs: Math.max(0, Date.now() - this.startedAt),
107
+ });
108
+ }
109
+ /**
110
+ * The wire shape. **Always a block, never `undefined`.**
111
+ *
112
+ * A clean page returns `{ observed: [...6 kinds], counts: {} }`, and that is
113
+ * the entire point rather than wasted bytes: it is the difference between "we
114
+ * listened and saw none" and "we did not look". The second is expressed by the
115
+ * scan carrying no `runtime` at all — which happens when this is not the first
116
+ * scan of a page load, or when the envelope predates the capability.
117
+ *
118
+ * A bare `consoleErrors: 0` could express neither, which is why no such field
119
+ * exists. Same rule `perf.ts` follows for CLS on engines that cannot measure it.
120
+ */
121
+ snapshot() {
122
+ return {
123
+ observed: [...OBSERVED_KINDS],
124
+ counts: { ...this.counts },
125
+ distinct: this.distinct.size,
126
+ omitted: this.omitted,
127
+ // First-seen rather than most-frequent: most-frequent would require keeping
128
+ // the full frequency map, which is the bound this class exists to hold.
129
+ exemplars: [...this.distinct.values()].slice(0, MAX_RUNTIME_EXEMPLARS),
130
+ };
131
+ }
132
+ }
133
+ const message = (value) => capLength(stripHostileCharacters(value), MAX_RUNTIME_MESSAGE_LENGTH);
134
+ /*
135
+ * Page-keyed, and held on a REGISTERED SYMBOL rather than in a module-level
136
+ * variable.
137
+ *
138
+ * This is the one piece of state that genuinely crosses module copies: the
139
+ * context fixture writes it and the two scan paths read it. A plain
140
+ * module-scoped `WeakMap` looks equivalent and is not — a package can be
141
+ * resolved twice in one process (ESM and CJS, or a source import beside a
142
+ * package import in a monorepo), and each copy would carry its own empty map.
143
+ * `runtime.ts` records the same hazard for the rule policy.
144
+ *
145
+ * Found the hard way: on the SDK's own fixture suite, auto-scans (reached through
146
+ * the source import) carried runtime evidence and explicit `setsquare.scan()`
147
+ * calls (reached through the package import) silently carried none. Nothing
148
+ * failed — the block was simply absent, which is indistinguishable from a clean
149
+ * page unless you know to look. Exactly the class of quiet wrongness this feature
150
+ * exists to expose in other people's tools.
151
+ */
152
+ const ACCUMULATORS = Symbol.for('setsquare.playwright.page-runtime');
153
+ function accumulatorMap() {
154
+ const store = globalThis;
155
+ const existing = store[ACCUMULATORS];
156
+ if (existing)
157
+ return existing;
158
+ const created = new WeakMap();
159
+ store[ACCUMULATORS] = created;
160
+ return created;
161
+ }
162
+ /**
163
+ * This page's runtime block, or `undefined` if the page was never observed.
164
+ *
165
+ * Callers gate this the way `perf` is gated — first scan of a `visitRef` only —
166
+ * because these are facts about a page LOAD, not about a scan. Scanning one page
167
+ * in four states must not report its console errors four times.
168
+ */
169
+ export function pageRuntime(page) {
170
+ return accumulatorMap().get(page)?.snapshot();
171
+ }
172
+ /**
173
+ * Attach the runtime listeners to one page.
174
+ *
175
+ * Never throws: an engine that refuses a listener must cost the customer nothing,
176
+ * and partial evidence beats none provided we do not pretend it is complete.
177
+ */
178
+ export function observePageRuntime(page, startedAt) {
179
+ const accumulator = new PageRuntimeAccumulator(startedAt);
180
+ accumulatorMap().set(page, accumulator);
181
+ try {
182
+ page.on('console', (entry) => {
183
+ // First line, so a page logging chattily at `log`/`info`/`debug` — which is
184
+ // most pages — allocates nothing.
185
+ const type = entry.type();
186
+ if (type !== 'error' && type !== 'warning')
187
+ return;
188
+ const kind = type === 'error' ? 'console-error' : 'console-warning';
189
+ const text = message(entry.text());
190
+ // Exemplar keys join on U+0000 throughout this file: it is banned from every
191
+ // string the contract accepts, so a message containing the separator cannot
192
+ // collapse two distinct events into one. Same convention as the dedupe key.
193
+ accumulator.add(kind, `${kind}\u0000${text}`, () => ({ message: text }));
194
+ });
195
+ page.on('pageerror', (error) => {
196
+ // Carry the message, never a parsed class name: stack and wording differ
197
+ // per engine, so a taxonomy built from them would be engine-dependent while
198
+ // looking canonical.
199
+ const text = message(error.message || String(error));
200
+ accumulator.add('page-error', `page-error\u0000${text}`, () => ({ message: text }));
201
+ });
202
+ page.on('requestfailed', (request) => {
203
+ const pattern = toUrlPattern(request.url()).pattern;
204
+ const errorText = request.failure()?.errorText;
205
+ const detail = errorText === undefined ? undefined : capLength(stripHostileCharacters(errorText), 128);
206
+ accumulator.add('request-failed', `request-failed\u0000${pattern}\u0000${detail ?? ''}`, () => ({ urlPattern: pattern, ...(detail === undefined ? {} : { errorText: detail }) }));
207
+ });
208
+ page.on('response', (response) => {
209
+ /*
210
+ * The hot path. Every response on every page reaches this line, so the
211
+ * cheap check comes first and the common case does no work beyond it.
212
+ *
213
+ * Only synchronous getters below. Reading a body here would buffer it and
214
+ * can deadlock a streaming request — see the header note; there is a test
215
+ * that greps this file to keep it that way.
216
+ */
217
+ const status = response.status();
218
+ if (status < 400)
219
+ return;
220
+ const kind = status >= 500 ? 'response-5xx' : 'response-4xx';
221
+ const pattern = toUrlPattern(response.url()).pattern;
222
+ accumulator.add(kind, `${kind}\u0000${status}\u0000${pattern}`, () => ({
223
+ urlPattern: pattern,
224
+ status,
225
+ }));
226
+ });
227
+ }
228
+ catch {
229
+ // A context or engine that refuses a listener yields no runtime evidence for
230
+ // that page. It must never cost the customer a test.
231
+ }
232
+ }
233
+ //# sourceMappingURL=observe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observe.js","sourceRoot":"","sources":["../src/observe.ts"],"names":[],"mappings":"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"}