@consenttheater/playbill 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,9 +6,9 @@
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-types%20included-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
7
7
  [![Node](https://img.shields.io/node/v/@consenttheater/playbill.svg)](package.json)
8
8
 
9
- **The Playbill** — an open-source, tiered knowledge base of GDPR-relevant web trackers, with pure-function matching and risk-scoring utilities.
9
+ **The Playbill** — an open-source, tiered knowledge base of GDPR-relevant web trackers, with pure-function matching helpers. Each entry is tagged with the **consent burden** it creates under EU/GDPR rules. No verdicts, no risk scores — just facts you can build on.
10
10
 
11
- A theater playbill lists every actor and their role on stage. This package does the same for the web: every tracking cookie, every tracking domain, every company behind them — identified, categorized, and scored against GDPR.
11
+ A theater playbill lists every actor and their role on stage. This package does the same for the web: every tracking cookie, every tracking domain, every company behind them — identified, categorised, and labelled with how much consent work each one creates.
12
12
 
13
13
  A standalone library — no browser dependencies, no runtime side effects, no lock-in. Useful for anyone building privacy tooling:
14
14
 
@@ -19,44 +19,44 @@ A standalone library — no browser dependencies, no runtime side effects, no lo
19
19
  - Academic research, regulatory studies, journalism projects
20
20
  - Your own privacy tools, commercial or otherwise (subject to the AGPL — see License)
21
21
 
22
+ ## Why no scoring?
23
+
24
+ Earlier releases (v0.1.x) shipped a `computeScore()` helper that produced a 0–100 compliance score and "compliant / violating" risk bands for whole sites. We removed it in v0.2.0.
25
+
26
+ Whether a site complies with GDPR is the work of supervisory authorities and courts. We are an evidence library, not a regulator. Downstream consumers — extensions, scanners, dashboards — can compute whatever ranking they want from the raw `consent_burden` and `category` fields. Keeping the judgement layer out of this package is the cleanest way to stay neutral.
27
+
22
28
  ## What's in the Playbill
23
29
 
24
- - **Cookie signatures** — name, owning company, service, purpose, severity, lifetime, docs link
25
- - **Domain signatures** — hostname, owning company, service, category, severity
30
+ - **Cookie signatures** — name, owning company, service, purpose, consent burden, lifetime, docs link
31
+ - **Domain signatures** — hostname, owning company, service, category, consent burden
26
32
  - **2,800+ companies** — from Google and Meta to regional EU ad networks and niche SaaS tools
27
33
  - **8,000+ entries** across 11 categories — one of the largest AGPL-licensed tracker databases available
28
34
  - **Matching utilities** — exact + pattern (trailing `*`) cookie matching, exact + subdomain hostname matching
29
- - **Scoring utilities** — GDPR-weighted compliance score with four risk bands
30
35
 
31
36
  ### Current stats
32
37
 
33
38
  | Metric | Count |
34
39
  |--------|-------|
35
- | Cookie signatures | 2,307 |
36
- | Domain signatures | 6,297 |
37
- | Total entries | 8,604 |
38
- | Unique companies | 2,839 |
40
+ | Cookie signatures | 2,197 |
41
+ | Domain signatures | 5,936 |
42
+ | Total entries | 8,133 |
43
+ | Unique companies | 2,829 |
39
44
  | Categories | 11 |
40
45
 
41
46
  ## Tiers
42
47
 
43
48
  Choose what you need — everything is **computed at runtime** from a single set of source files, no pre-built tier bundles to drift out of sync:
44
49
 
45
- | Tier | Entries | Companies | Size (gzip) | Use case |
46
- |------|---------|-----------|-------------|----------|
47
- | `mini` | ~620 | ~45 | ~25 KB | Lightweight widgets, top-50 company quick checks |
48
- | `core` | ~7,000 | ~2,470 | ~275 KB | CI/CD scanners, most compliance tools |
49
- | `full` | ~8,100 | ~2,825 | ~320 KB | Complete audits, regional/niche coverage |
50
-
51
- **Tier semantics:**
52
- - `mini` — top 50 companies by entry count, `critical` + `high` severity only
53
- - `core` — all `critical` + `high` + `medium` severity, any company
54
- - `full` — everything, including `low` severity, regional, and niche
50
+ | Tier | Selection | Use case |
51
+ |------|-----------|----------|
52
+ | `mini` | Top 50 companies; `required_strict` + `required` only | Lightweight widgets, top-50 company quick checks |
53
+ | `core` | All consent-requiring entries (`required_strict`, `required`, `contested`) | CI/CD scanners, most compliance tools |
54
+ | `full` | Everything, including `minimal`-burden entries | Complete audits, regional/niche coverage |
55
55
 
56
56
  ## Usage
57
57
 
58
58
  ```ts
59
- import { loadPlaybill, matchCookie, matchDomain, computeScore } from '@consenttheater/playbill';
59
+ import { loadPlaybill, matchCookie, matchDomain } from '@consenttheater/playbill';
60
60
 
61
61
  // Load the tier you need
62
62
  const playbill = loadPlaybill('core');
@@ -68,7 +68,7 @@ const cookie = matchCookie(playbill, '_ga');
68
68
  // company: 'Google',
69
69
  // service: 'Google Analytics',
70
70
  // category: 'analytics',
71
- // severity: 'high',
71
+ // consent_burden: 'required',
72
72
  // description: 'Distinguishes unique users...',
73
73
  // lifetime: '2 years',
74
74
  // docs_url: 'https://developers.google.com/...'
@@ -77,18 +77,7 @@ const cookie = matchCookie(playbill, '_ga');
77
77
  // Identify a domain (exact or subdomain match)
78
78
  const domain = matchDomain(playbill, 'connect.facebook.net');
79
79
  // → { hostname: 'connect.facebook.net', company: 'Meta',
80
- // service: 'Meta Pixel', category: 'advertising', severity: 'critical' }
81
-
82
- // Score a page's compliance against GDPR
83
- const result = computeScore({
84
- preConsentCookies: [cookie],
85
- preConsentRequests: [domain],
86
- dataLeakRequests: [],
87
- banner: { detected: true, hasAcceptButton: true, hasRejectButton: false }
88
- });
89
- // → { score: 45,
90
- // band: { key: 'non_compliant', label: 'Non-Compliant' },
91
- // violations: [...] }
80
+ // service: 'Meta Pixel', category: 'advertising', consent_burden: 'required_strict' }
92
81
  ```
93
82
 
94
83
  ### Loading individual categories
@@ -113,14 +102,13 @@ import dataLeak from '@consenttheater/playbill/actors/data-leak';
113
102
  // consent, fingerprinting, tag-manager
114
103
  ```
115
104
 
116
- ### Matcher-only / scorer-only
105
+ ### Matcher-only
117
106
 
118
- If you only need matching (no scoring) or scoring (no DB):
107
+ If you only need matching (and want to skip importing the bundled actor JSON):
119
108
 
120
109
  ```ts
121
110
  import { matchCookie, matchDomain } from '@consenttheater/playbill/matcher';
122
- import { computeScore, bandForScore, SEVERITY_WEIGHTS, BANDS } from '@consenttheater/playbill/scorer';
123
- import type { Playbill, CookieActor, ScoreResult } from '@consenttheater/playbill/types';
111
+ import type { Playbill, CookieActor } from '@consenttheater/playbill/types';
124
112
  ```
125
113
 
126
114
  ## Categories
@@ -141,27 +129,20 @@ import type { Playbill, CookieActor, ScoreResult } from '@consenttheater/playbil
141
129
 
142
130
  ### The `data_leak` category is special
143
131
 
144
- Entries scored as `data_leak` (Google Fonts, Typekit, YouTube embeds, Google Maps, etc.) are counted as violations **even after consent**. Rationale: the Austrian DPA ruling (2022) and LG München judgments hold that IP exfiltration to third parties violates GDPR regardless of consent, because the request fires before any dialog can mediate.
132
+ Entries categorised as `data_leak` (Google Fonts, Typekit, YouTube embeds, Google Maps, etc.) are noteworthy **even after consent**. Rationale: the Austrian DPA ruling (2022) and LG München judgments hold that IP exfiltration to third parties is a separate concern from cookie consent, because the request fires before any dialog can mediate. We tag the entries; how you treat them in your UI is your call.
145
133
 
146
- ## Severity levels
134
+ ## Consent burden
147
135
 
148
- | Severity | GDPR weight | Meaning |
149
- |----------|-------------|---------|
150
- | `critical` | -25 points | Ad/retargeting trackers — clear GDPR violation if set before consent |
151
- | `high` | -15 points | Analytics without legal basis; banner missing reject option |
152
- | `medium` | -10 points | Session recording, data leaks — elevated risk exposure |
153
- | `low` | -5 points | Functional/security — typically exempt under legitimate interest |
136
+ Every entry carries a `consent_burden` value describing how much explicit consent the tracker needs under GDPR / ePrivacy.
154
137
 
155
- ## Risk bands
138
+ | Value | Meaning | Examples |
139
+ |-------|---------|----------|
140
+ | `required_strict` | Cross-site profiling, ad-tech retargeting, fingerprinting, session recording. Always needs prior, informed, freely-given consent. | DoubleClick, Meta Pixel, Hotjar, FingerprintJS |
141
+ | `required` | Standard analytics and marketing tracking. Consent required in nearly all interpretations. | Google Analytics, Mixpanel, HubSpot tracking |
142
+ | `contested` | Tracking-adjacent or jurisdiction-dependent. Some authorities allow under legitimate interest, others require consent. Treat as consent-required by default. | Some session storage IDs, certain CDP cookies |
143
+ | `minimal` | Functional, security, or strictly-necessary in most interpretations. Often exempt from consent requirements. | CSRF tokens, language preferences, opt-out flags |
156
144
 
157
- `computeScore()` returns one of four bands based on the total score (100 Σ weights):
158
-
159
- | Score | Band | Meaning |
160
- |-------|------|---------|
161
- | ≥ 90 | `compliant` | GDPR-clean or near-clean |
162
- | 70–89 | `at_risk` | Minor issues — one critical violation drops you here |
163
- | 40–69 | `non_compliant` | Two critical violations or equivalent |
164
- | < 40 | `violating` | Four+ critical violations; systemic failure |
145
+ These labels describe **what kind of GDPR work the tracker creates**, not whether any particular site is compliant. Two trackers in the same category can carry different burdens depending on the operator's role and how they're used.
165
146
 
166
147
  ## Pattern cookies
167
148
 
@@ -182,9 +163,7 @@ import type {
182
163
  Playbill, Tier,
183
164
  CookieActor, DomainActor,
184
165
  CookieMatch, DomainMatch,
185
- Severity, Category,
186
- ScoreInput, ScoreResult, Violation,
187
- Band, BandKey,
166
+ ConsentBurden, Category
188
167
  } from '@consenttheater/playbill';
189
168
  ```
190
169
 
@@ -196,12 +175,12 @@ The AGPL is a deliberate choice: the tracker knowledge encoded here represents s
196
175
 
197
176
  ## Contributing
198
177
 
199
- Found a tracker we're missing? Want to fix an incorrect severity or update a lifetime? PRs welcome.
178
+ Found a tracker we're missing? Want to correct a `consent_burden` value or update a lifetime? PRs welcome.
200
179
 
201
180
  Each entry needs:
202
181
  - Cookie name or domain
203
182
  - Owning company and service name
204
- - Category and severity
183
+ - Category and `consent_burden`
205
184
  - One-sentence description
206
185
  - Cookie lifetime (for cookies)
207
186
  - Link to official documentation
@@ -211,3 +190,14 @@ After editing any file under `src/actors/`, run:
211
190
  ```sh
212
191
  npm run normalize # sorts keys, reformats, flags duplicates, updates stats
213
192
  ```
193
+
194
+ ## Migrating from v0.1.x
195
+
196
+ v0.2.0 is a breaking change. See [CHANGELOG.md](./CHANGELOG.md) for the full migration guide. In short:
197
+
198
+ - `severity` field renamed to `consent_burden` with descriptive labels:
199
+ - `critical` → `required_strict`
200
+ - `high` → `required`
201
+ - `medium` → `contested`
202
+ - `low` → `minimal`
203
+ - The whole `scorer` module (`computeScore`, `bandForScore`, `SEVERITY_WEIGHTS`, `BANDS`, `Violation`, `ScoreResult`, `Band`, `BandKey`) was removed. Compute presentation hierarchies in your own UI layer.