privalint 0.3.0 → 0.4.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 (64) hide show
  1. package/README.de.md +38 -0
  2. package/README.md +49 -11
  3. package/dist/assessment.d.ts +1 -1
  4. package/dist/assessment.js +45 -9
  5. package/dist/assessment.js.map +1 -1
  6. package/dist/capture.js +10 -3
  7. package/dist/capture.js.map +1 -1
  8. package/dist/cli.js +44 -11
  9. package/dist/cli.js.map +1 -1
  10. package/dist/config.d.ts +21 -0
  11. package/dist/config.js +113 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/consent.js +70 -8
  14. package/dist/consent.js.map +1 -1
  15. package/dist/coverage.d.ts +13 -0
  16. package/dist/coverage.js +86 -0
  17. package/dist/coverage.js.map +1 -0
  18. package/dist/data/third-parties.js +9 -0
  19. package/dist/data/third-parties.js.map +1 -1
  20. package/dist/diagnostics.d.ts +7 -3
  21. package/dist/diagnostics.js +36 -8
  22. package/dist/diagnostics.js.map +1 -1
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.js +3 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/network.d.ts +3 -2
  27. package/dist/network.js +6 -4
  28. package/dist/network.js.map +1 -1
  29. package/dist/observations.d.ts +5 -1
  30. package/dist/observations.js +6 -1
  31. package/dist/observations.js.map +1 -1
  32. package/dist/policy.d.ts +6 -0
  33. package/dist/policy.js +37 -0
  34. package/dist/policy.js.map +1 -0
  35. package/dist/report-contract.d.ts +13 -0
  36. package/dist/report-contract.js +16 -0
  37. package/dist/report-contract.js.map +1 -0
  38. package/dist/reporters/capture.js +56 -4
  39. package/dist/reporters/capture.js.map +1 -1
  40. package/dist/reporters/markdown.js +6 -1
  41. package/dist/reporters/markdown.js.map +1 -1
  42. package/dist/reporters/messages.d.ts +1 -0
  43. package/dist/reporters/messages.js +6 -0
  44. package/dist/reporters/messages.js.map +1 -1
  45. package/dist/reporters/sarif.js +25 -11
  46. package/dist/reporters/sarif.js.map +1 -1
  47. package/dist/reporters/shared.js +3 -2
  48. package/dist/reporters/shared.js.map +1 -1
  49. package/dist/reporters/text.js +4 -0
  50. package/dist/reporters/text.js.map +1 -1
  51. package/dist/rules/reject-option.js +3 -1
  52. package/dist/rules/reject-option.js.map +1 -1
  53. package/dist/rules/third-party-embeds.js +2 -2
  54. package/dist/rules/third-party-embeds.js.map +1 -1
  55. package/dist/scan-options.d.ts +7 -1
  56. package/dist/scan-options.js.map +1 -1
  57. package/dist/scanner.js +95 -7
  58. package/dist/scanner.js.map +1 -1
  59. package/dist/types.d.ts +61 -2
  60. package/package.json +7 -1
  61. package/schemas/report-1.0.0.schema.json +813 -0
  62. package/schemas/report-1.1.0.schema.json +833 -0
  63. package/schemas/sarif-properties-1.0.0.schema.json +785 -0
  64. package/schemas/sarif-properties-1.1.0.schema.json +810 -0
@@ -1 +1 @@
1
- {"version":3,"file":"third-party-embeds.js","sourceRoot":"","sources":["../../src/rules/third-party-embeds.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,EAAE,GAAG,oBAAoB,CAAC;AAEhC,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,EAAE;IACN,KAAK,EAAE,uCAAuC;IAC9C,WAAW,EACT,6FAA6F;QAC7F,wFAAwF;QACxF,iEAAiE;IACnE,UAAU,EAAE,CAAC,gBAAgB,EAAE,mBAAmB,CAAC;IACnD,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;QAClB,OAAO,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAC7D,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAW,EAAE,CAAC,CAAC;YAChC,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE;gBACjB,EAAE,EAAE,GAAG,MAAM,8CAA8C;gBAC3D,EAAE,EAAE,GAAG,MAAM,kDAAkD;aAChE,CAAC;YACF,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,OAAO,EAAE,MAAM;YACf,QAAQ;YACR,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE;gBACb,EAAE,EAAE,+BAA+B,MAAM,6GAA6G;gBACtJ,EAAE,EAAE,gCAAgC,MAAM,gIAAgI;aAC3K,CAAC;SACH,CAAC,CACH,CAAC;IACJ,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"third-party-embeds.js","sourceRoot":"","sources":["../../src/rules/third-party-embeds.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,EAAE,GAAG,oBAAoB,CAAC;AAEhC,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,EAAE;IACN,KAAK,EAAE,uCAAuC;IAC9C,WAAW,EACT,6FAA6F;QAC7F,wFAAwF;QACxF,iEAAiE;IACnE,UAAU,EAAE,CAAC,gBAAgB,EAAE,mBAAmB,CAAC;IACnD,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;QAClB,OAAO,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAC7D,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAW,EAAE,CAAC,CAAC;YAChC,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE;gBACjB,EAAE,EAAE,GAAG,MAAM,8CAA8C;gBAC3D,EAAE,EAAE,GAAG,MAAM,kDAAkD;aAChE,CAAC;YACF,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,OAAO,EAAE,MAAM;YACf,QAAQ;YACR,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE;gBACb,EAAE,EAAE,0CAA0C,MAAM,8JAA8J;gBAClN,EAAE,EAAE,iCAAiC,MAAM,yMAAyM;aACrP,CAAC;SACH,CAAC,CACH,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import type { Lang } from './i18n.js';
2
2
  import type { Region } from './legal.js';
3
3
  import type { NetworkAdapter, NetworkLimits } from './network.js';
4
- import type { PageSnapshot, Rule } from './types.js';
4
+ import type { PageSnapshot, Rule, RuleSettings, ScanProgressEvent } from './types.js';
5
5
  export interface ScanOptions {
6
6
  maxPages?: number | undefined;
7
7
  settleMs?: number | undefined;
@@ -12,6 +12,12 @@ export interface ScanOptions {
12
12
  /** Tool classification profile; does not determine which law applies. */
13
13
  region?: Region | undefined;
14
14
  rules?: readonly Rule[];
15
+ ruleSettings?: RuleSettings;
16
+ allow?: {
17
+ vendors: readonly string[];
18
+ };
19
+ /** Synchronous notification; exceptions propagate after resource cleanup. */
20
+ onProgress?: (event: ScanProgressEvent) => void;
15
21
  /** Legacy test helper: third-party requests receive synthetic empty responses. */
16
22
  offline?: boolean;
17
23
  consentCheck?: boolean | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"scan-options.js","sourceRoot":"","sources":["../src/scan-options.ts"],"names":[],"mappings":"AAkCA,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"scan-options.js","sourceRoot":"","sources":["../src/scan-options.ts"],"names":[],"mappings":"AAsCA,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC"}
package/dist/scanner.js CHANGED
@@ -1,9 +1,13 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import { chromium } from 'playwright';
2
3
  import { assessPage } from './assessment.js';
3
4
  import { capturePage } from './capture.js';
4
5
  import { diagnosticUrl } from './diagnostics.js';
5
6
  import { applyRegion } from './legal.js';
7
+ import { VERSION } from './meta.js';
6
8
  import { networkLimits } from './network.js';
9
+ import { applyPolicy, ruleSetting, validateRuleSettings } from './policy.js';
10
+ import { REPORT_SCHEMA_VERSION } from './report-contract.js';
7
11
  import { defaultRules } from './rules/index.js';
8
12
  import { DEFAULTS } from './scan-options.js';
9
13
  import { crawlTarget, withoutHash } from './url.js';
@@ -19,7 +23,17 @@ export function throwIfAborted(signal) {
19
23
  export async function scan(target, options = {}) {
20
24
  throwIfAborted(options.signal);
21
25
  const startedAt = Date.now();
22
- const rules = options.rules ?? defaultRules;
26
+ const scanId = randomUUID();
27
+ const emit = (event) => options.onProgress?.({ ...event, scanId, elapsedMs: Date.now() - startedAt });
28
+ emit({ stage: 'starting', elapsedMs: 0 });
29
+ const configuredRules = options.rules ?? defaultRules;
30
+ validateRuleSettings(options.ruleSettings ?? {}, [...defaultRules, ...configuredRules]);
31
+ if (options.allow &&
32
+ (!Array.isArray(options.allow.vendors) ||
33
+ !options.allow.vendors.every((vendor) => typeof vendor === 'string' && vendor.length > 0))) {
34
+ throw new TypeError('allow.vendors must contain non-empty vendor names');
35
+ }
36
+ const rules = configuredRules.filter((rule) => ruleSetting(options.ruleSettings, rule.id) !== 'off');
23
37
  const maxPages = options.maxPages ?? DEFAULTS.maxPages;
24
38
  integer(maxPages, 'maxPages', 1);
25
39
  integer(options.settleMs ?? DEFAULTS.settleMs, 'settleMs', 0);
@@ -49,12 +63,35 @@ export async function scan(target, options = {}) {
49
63
  const snapshots = [];
50
64
  const queue = [siteUrl.href];
51
65
  const seen = new Set(queue);
52
- const captured = new Set();
66
+ const pageIds = new Map();
53
67
  let url = queue.shift();
54
68
  while (url !== undefined && snapshots.length < maxPages) {
55
69
  throwIfAborted(options.signal);
56
70
  const isStart = snapshots.length === 0;
57
- const snapshot = await capturePage(browser, url, siteUrl, options, isStart);
71
+ const pageIndex = snapshots.length;
72
+ const captureId = randomUUID();
73
+ emit({
74
+ stage: 'loading-page',
75
+ elapsedMs: 0,
76
+ pageUrl: diagnosticUrl(url),
77
+ pageIndex,
78
+ captureId,
79
+ });
80
+ let progressFailure;
81
+ const snapshot = await capturePage(browser, url, siteUrl, {
82
+ ...options,
83
+ onProgress: (event) => {
84
+ try {
85
+ emit({ ...event, pageIndex, captureId });
86
+ }
87
+ catch (error) {
88
+ progressFailure = { error };
89
+ throw error;
90
+ }
91
+ },
92
+ }, isStart);
93
+ if (progressFailure)
94
+ throw progressFailure.error;
58
95
  if (isStart) {
59
96
  const failureMode = options.failureMode ?? (options.networkAdapter ? 'report' : 'throw');
60
97
  if (snapshot.error !== undefined && failureMode === 'throw') {
@@ -63,8 +100,22 @@ export async function scan(target, options = {}) {
63
100
  siteUrl = new URL(snapshot.finalUrl);
64
101
  }
65
102
  const finalUrl = withoutHash(snapshot.finalUrl);
66
- if (!captured.has(finalUrl)) {
67
- captured.add(finalUrl);
103
+ const existingPage = pageIds.get(finalUrl);
104
+ const { pageId, pageIndex: resolvedIndex } = existingPage ?? {
105
+ pageId: randomUUID(),
106
+ pageIndex,
107
+ };
108
+ pageIds.set(finalUrl, { pageId, pageIndex: resolvedIndex });
109
+ snapshot.pageId = pageId;
110
+ emit({
111
+ stage: 'page-captured',
112
+ elapsedMs: 0,
113
+ pageUrl: diagnosticUrl(snapshot.finalUrl),
114
+ captureId,
115
+ pageId,
116
+ pageIndex: resolvedIndex,
117
+ });
118
+ if (existingPage === undefined) {
68
119
  seen.add(finalUrl);
69
120
  snapshots.push(snapshot);
70
121
  options.onPage?.(snapshot);
@@ -79,15 +130,51 @@ export async function scan(target, options = {}) {
79
130
  url = queue.shift();
80
131
  }
81
132
  throwIfAborted(options.signal);
82
- const assessments = snapshots.map((page, index) => assessPage(page, rules, siteUrl, lang, index === 0, options.consentCheck !== false));
133
+ const assessments = snapshots.map((page, index) => {
134
+ emit({
135
+ stage: 'evaluating-rules',
136
+ elapsedMs: 0,
137
+ pageIndex: index,
138
+ ...(page.pageId === undefined ? {} : { pageId: page.pageId }),
139
+ pageUrl: diagnosticUrl(page.finalUrl),
140
+ });
141
+ return assessPage(page, rules, siteUrl, lang, index === 0, options.consentCheck !== false, configuredRules);
142
+ });
83
143
  const partial = assessments.some((assessment) => assessment.evaluations.some((evaluation) => evaluation.partial || evaluation.reason === 'consent-disabled')) || snapshots.some((page) => !page.capture?.complete);
84
144
  const result = {
145
+ scanId,
146
+ schemaVersion: REPORT_SCHEMA_VERSION,
147
+ scannerVersion: VERSION,
148
+ options: {
149
+ maxPages,
150
+ settleMs: options.settleMs ?? DEFAULTS.settleMs,
151
+ timeoutMs: options.timeoutMs ?? DEFAULTS.timeoutMs,
152
+ locale: options.locale ?? DEFAULTS.locale,
153
+ lang,
154
+ region,
155
+ consentCheck: options.consentCheck !== false,
156
+ headed: options.headed === true,
157
+ channel: options.channel ?? 'chromium',
158
+ captureTimeoutMs: options.captureTimeoutMs ?? (options.networkAdapter ? 60_000 : null),
159
+ maxDiagnostics: options.maxDiagnostics ?? 100,
160
+ failureMode: options.failureMode ?? (options.networkAdapter ? 'report' : 'throw'),
161
+ captureMode: options.networkAdapter
162
+ ? 'adapter'
163
+ : options.offline
164
+ ? 'offline-fixture'
165
+ : 'native',
166
+ networkLimits: options.networkAdapter ? networkLimits(options.networkLimits) : null,
167
+ selectedRules: rules.map((rule) => rule.id),
168
+ ruleSettings: { ...options.ruleSettings },
169
+ allowedVendors: [...(options.allow?.vendors ?? [])],
170
+ },
85
171
  siteUrl: siteUrl.href,
86
172
  lang,
87
173
  region,
88
174
  scannedAt: new Date(startedAt).toISOString(),
89
175
  durationMs: Date.now() - startedAt,
90
176
  pages: snapshots.map((page, index) => ({
177
+ ...(page.pageId === undefined ? {} : { pageId: page.pageId }),
91
178
  url: page.url,
92
179
  finalUrl: page.finalUrl,
93
180
  status: page.status,
@@ -98,10 +185,11 @@ export async function scan(target, options = {}) {
98
185
  ruleEvaluations: assessments[index]?.evaluations ?? [],
99
186
  })),
100
187
  ...consentSummary(snapshots[0]),
101
- findings: applyRegion(assessments.flatMap((assessment) => assessment.findings), region),
188
+ findings: applyPolicy(applyRegion(assessments.flatMap((assessment) => assessment.findings), region), options.ruleSettings, options.allow?.vendors),
102
189
  rules: rules.map(({ check: _check, ...meta }) => meta),
103
190
  coverage: partial ? 'partial' : 'complete',
104
191
  };
192
+ emit({ stage: 'completed', elapsedMs: 0 });
105
193
  return options.networkAdapter ? redactReport(result) : result;
106
194
  }
107
195
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -7,9 +7,12 @@ export interface RecordedRequest {
7
7
  /** Absent on legacy snapshots. Only received responses count as network evidence. */
8
8
  outcome?: 'pending' | 'response' | 'failed';
9
9
  status?: number;
10
+ /** Set when the network adapter deliberately did not send the request. */
11
+ skippedReason?: SkipReason;
10
12
  }
11
- export type LoadIssueKind = 'security-blocked' | 'unsupported-method' | 'unsupported-protocol' | 'dns' | 'tls' | 'connection' | 'timeout' | 'resource-limit' | 'http-error' | 'browser-failure' | 'aborted';
13
+ export type LoadIssueKind = 'security-blocked' | 'unsupported-method' | 'unsupported-protocol' | 'dns' | 'tls' | 'connection' | 'timeout' | 'resource-limit' | 'http-error' | 'browser-failure' | 'skipped' | 'aborted';
12
14
  export type CapturePhase = 'before-consent' | 'after-reject';
15
+ export type SkipReason = 'beacon' | 'unsupported-method' | 'unsupported-protocol' | 'policy';
13
16
  export interface LoadDiagnostic {
14
17
  kind: LoadIssueKind;
15
18
  phase: CapturePhase;
@@ -17,8 +20,13 @@ export interface LoadDiagnostic {
17
20
  url: string;
18
21
  status?: number;
19
22
  limit?: 'requests' | 'response-bytes' | 'total-bytes' | 'redirects';
23
+ skippedReason?: SkipReason;
20
24
  }
21
25
  export interface LoadDiagnostics {
26
+ /** Disjoint terminal outcomes; finished + these three equals requests. */
27
+ skippedRequests?: number;
28
+ failedRequests?: number;
29
+ securityBlockedRequests?: number;
22
30
  /** HTTP(S) browser requests, including documents and every redirect hop, across both phases. */
23
31
  requests: number;
24
32
  /** Requests counted but omitted from bounded in-memory rule evidence. */
@@ -27,7 +35,7 @@ export interface LoadDiagnostics {
27
35
  responses: number;
28
36
  /** Browser requestfinished events (including HTTP errors). */
29
37
  finished: number;
30
- /** Failed or unfinished requests at capture end; disjoint from finished. */
38
+ /** @deprecated Aggregate of skippedRequests + failedRequests + securityBlockedRequests. */
31
39
  failed: number;
32
40
  /** Subset of failed: explicitly denied by the adapter's security policy. */
33
41
  blocked: number;
@@ -42,12 +50,17 @@ export interface LoadDiagnostics {
42
50
  }
43
51
  export type ObservationKind = 'document' | 'network' | 'consent' | 'after-reject';
44
52
  export interface RuleEvaluation {
53
+ pageId?: string;
45
54
  ruleId: string;
46
55
  status: 'executed' | 'skipped' | 'not-evaluable';
47
56
  reason?: 'disabled' | 'consent-disabled' | 'not-start-page' | 'missing-observation';
48
57
  /** Executed against available positive evidence, without ruling out additional findings. */
49
58
  partial: boolean;
59
+ outcome?: 'checked-no-finding' | 'finding-detected' | 'not-evaluable';
60
+ explanation?: RuleExplanation;
61
+ findingCount?: number;
50
62
  }
63
+ export type RuleExplanation = 'disabled' | 'not-start-page' | 'consent-disabled' | 'missing-reject-observation' | 'missing-consent-observation' | 'incomplete-document' | 'positive-evidence' | 'incomplete-observation' | 'required-observations-available' | 'no-supported-banner' | 'no-supported-reject-control' | 'unsupported-banner-markup' | 'browser-interaction-failed' | 'reject-clicked-and-reloaded';
51
64
  export interface CaptureObservation {
52
65
  complete: boolean;
53
66
  /** Loading coverage before the consent interaction, for pre-consent rule evaluation. */
@@ -73,6 +86,8 @@ export interface ResourceHint {
73
86
  }
74
87
  /** What happened when privalint looked for a consent banner and clicked "reject". */
75
88
  export interface ConsentObservation {
89
+ outcome?: 'no-banner-detected' | 'unsupported-banner' | 'interaction-failed' | 'reject-succeeded';
90
+ reason?: 'no-supported-banner' | 'no-supported-reject-control' | 'unsupported-banner-markup' | 'browser-interaction-failed' | 'reject-clicked-and-reloaded';
76
91
  state?: 'not-detected' | 'reject-unavailable' | 'interaction-failed' | 'reject-tested';
77
92
  bannerFound: boolean;
78
93
  /** Name of the consent manager, if it was recognised. */
@@ -97,6 +112,7 @@ export interface ConsentObservation {
97
112
  * without touching any consent banner.
98
113
  */
99
114
  export interface PageSnapshot {
115
+ pageId?: string;
100
116
  url: string;
101
117
  finalUrl: string;
102
118
  status: number | null;
@@ -113,6 +129,12 @@ export interface PageSnapshot {
113
129
  capture?: CaptureObservation;
114
130
  }
115
131
  export interface Finding {
132
+ pageId?: string;
133
+ /** Explicit local policy, not evidence of consent or legal approval. */
134
+ policy?: {
135
+ allowed: boolean;
136
+ originalSeverity: Severity;
137
+ };
116
138
  ruleId: string;
117
139
  severity: Severity;
118
140
  message: string;
@@ -141,6 +163,7 @@ export interface Rule {
141
163
  check(context: RuleContext): Finding[];
142
164
  }
143
165
  export interface PageSummary {
166
+ pageId?: string;
144
167
  url: string;
145
168
  finalUrl: string;
146
169
  status: number | null;
@@ -152,6 +175,11 @@ export interface PageSummary {
152
175
  }
153
176
  export type ConsentSummary = Omit<ConsentObservation, 'afterReject'>;
154
177
  export interface ScanResult {
178
+ scanId?: string;
179
+ /** Absent on reports created before schema versioning. */
180
+ schemaVersion?: string;
181
+ scannerVersion?: string;
182
+ options?: ReportOptions;
155
183
  siteUrl: string;
156
184
  lang: Lang;
157
185
  region: Region;
@@ -165,3 +193,34 @@ export interface ScanResult {
165
193
  /** Observation coverage, not a legal compliance judgement. */
166
194
  coverage?: 'complete' | 'partial';
167
195
  }
196
+ export type RuleSettings = Record<string, Severity | 'off'>;
197
+ export interface ScanProgressEvent {
198
+ stage: 'starting' | 'loading-page' | 'checking-consent' | 'page-captured' | 'evaluating-rules' | 'completed';
199
+ /** Random attempt ID; multiple redirecting attempts may resolve to the same pageId. */
200
+ captureId?: string;
201
+ pageId?: string;
202
+ scanId?: string;
203
+ elapsedMs: number;
204
+ /** Origin-only, no target path, credentials, query or fragment. */
205
+ pageUrl?: string;
206
+ pageIndex?: number;
207
+ }
208
+ export interface ReportOptions {
209
+ maxPages: number;
210
+ settleMs: number;
211
+ timeoutMs: number;
212
+ locale: string;
213
+ lang: Lang;
214
+ region: Region;
215
+ consentCheck: boolean;
216
+ headed: boolean;
217
+ channel: string;
218
+ captureTimeoutMs: number | null;
219
+ maxDiagnostics: number;
220
+ failureMode: 'throw' | 'report';
221
+ captureMode: 'native' | 'adapter' | 'offline-fixture';
222
+ networkLimits: Record<string, number> | null;
223
+ selectedRules: string[];
224
+ ruleSettings: RuleSettings;
225
+ allowedVendors: string[];
226
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "privalint",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Lint your website for GDPR problems: trackers before consent and after reject, Google Fonts, embeds, missing Impressum. Real browser, CLI and GitHub Action.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,12 +9,14 @@
9
9
  "main": "dist/index.js",
10
10
  "types": "dist/index.d.ts",
11
11
  "exports": {
12
+ "./schemas/*": "./schemas/*",
12
13
  ".": {
13
14
  "types": "./dist/index.d.ts",
14
15
  "default": "./dist/index.js"
15
16
  }
16
17
  },
17
18
  "files": [
19
+ "schemas",
18
20
  "dist",
19
21
  "README.de.md"
20
22
  ],
@@ -24,6 +26,9 @@
24
26
  "scripts": {
25
27
  "build": "tsc -p tsconfig.build.json",
26
28
  "typecheck": "tsc --noEmit",
29
+ "schemas:build": "node scripts/build-report-schemas.mjs",
30
+ "schemas:check": "node scripts/build-report-schemas.mjs --check",
31
+ "fixtures:reports": "npm run build && node scripts/build-report-fixtures.mjs",
27
32
  "test": "vitest run",
28
33
  "test:watch": "vitest",
29
34
  "prepublishOnly": "npm run build",
@@ -55,6 +60,7 @@
55
60
  "devDependencies": {
56
61
  "@biomejs/biome": "2.6.3",
57
62
  "@types/node": "^20.19.43",
63
+ "ajv": "^8.20.0",
58
64
  "typescript": "^7.0.2",
59
65
  "vitest": "^4.1.12"
60
66
  },