@consenttheater/playbill 0.1.1 → 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 +49 -59
- package/dist/actors/advertising.json +2413 -2412
- package/dist/actors/analytics.json +2653 -2648
- package/dist/actors/consent.json +89 -89
- package/dist/actors/data_leak.json +822 -819
- package/dist/actors/fingerprinting.json +205 -205
- package/dist/actors/functional.json +1098 -1092
- package/dist/actors/marketing.json +728 -727
- package/dist/actors/security.json +90 -90
- package/dist/actors/session_recording.json +161 -161
- package/dist/actors/social.json +325 -325
- package/dist/actors/tag_manager.json +44 -44
- package/dist/index.d.ts +16 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -12
- package/dist/types.d.ts +25 -29
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +8 -3
- package/package.json +3 -7
- package/dist/scorer.d.ts +0 -42
- package/dist/scorer.d.ts.map +0 -1
- package/dist/scorer.js +0 -97
|
@@ -3,51 +3,51 @@
|
|
|
3
3
|
"description": "Tag management systems — container scripts that load other trackers",
|
|
4
4
|
"stats": { "cookies": 10, "domains": 34, "companies": 25 },
|
|
5
5
|
"cookies": {
|
|
6
|
-
"_dc_gtm_*": { "company": "Google", "service": "Google Tag Manager", "category": "tag_manager", "description": "Throttles request rate for Google Tag Manager container loading", "
|
|
7
|
-
"_zaius_*": { "company": "Optimizely (Zaius)", "service": "Zaius CDP", "category": "tag_manager", "description": "Zaius/Optimizely Data Platform cookie for B2C customer data collection and tag management", "
|
|
8
|
-
"ensighten_*": { "company": "Ensighten", "service": "Ensighten Manage", "category": "tag_manager", "description": "Ensighten tag management cookie for controlling tag firing rules and visitor segmentation", "
|
|
9
|
-
"lytics_*": { "company": "Lytics", "service": "Lytics CDP", "category": "tag_manager", "description": "Lytics CDP tag management cookie for real-time audience decisioning and tag orchestration", "
|
|
10
|
-
"mp_*_api_host_override": { "company": "mParticle", "service": "mParticle SDK", "category": "tag_manager", "description": "mParticle API host override cookie for routing SDK calls through custom proxy endpoints", "
|
|
11
|
-
"rl_*": { "company": "RudderStack", "service": "RudderStack SDK", "category": "tag_manager", "description": "RudderStack open-source CDP cookie storing anonymous ID, user traits, and session data for tag routing", "
|
|
12
|
-
"tdjs_*": { "company": "Treasure Data", "service": "Treasure Data JS SDK", "category": "tag_manager", "description": "Treasure Data CDP JavaScript SDK cookie for event collection and visitor identification", "
|
|
13
|
-
"tt_tealium_ct": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "description": "Tealium connection type cookie for tag management load rules", "
|
|
14
|
-
"utag_main": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "description": "Primary Tealium visitor session cookie containing session ID and visit count", "
|
|
15
|
-
"utag_main_*": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "description": "Extended Tealium session data used for tag firing conditions and visitor stitching", "
|
|
6
|
+
"_dc_gtm_*": { "company": "Google", "service": "Google Tag Manager", "category": "tag_manager", "description": "Throttles request rate for Google Tag Manager container loading", "consent_burden": "contested", "pattern": true, "lifetime": "1 minute", "docs_url": "https://developers.google.com/tag-platform/tag-manager/web" },
|
|
7
|
+
"_zaius_*": { "company": "Optimizely (Zaius)", "service": "Zaius CDP", "category": "tag_manager", "description": "Zaius/Optimizely Data Platform cookie for B2C customer data collection and tag management", "consent_burden": "required", "pattern": true, "lifetime": "1 year", "docs_url": "https://www.optimizely.com/legal/privacy-policy/" },
|
|
8
|
+
"ensighten_*": { "company": "Ensighten", "service": "Ensighten Manage", "category": "tag_manager", "description": "Ensighten tag management cookie for controlling tag firing rules and visitor segmentation", "consent_burden": "contested", "pattern": true, "lifetime": "1 year", "docs_url": "https://www.ensighten.com/privacy-policy/" },
|
|
9
|
+
"lytics_*": { "company": "Lytics", "service": "Lytics CDP", "category": "tag_manager", "description": "Lytics CDP tag management cookie for real-time audience decisioning and tag orchestration", "consent_burden": "required", "pattern": true, "lifetime": "1 year", "docs_url": "https://www.lytics.com/privacy/" },
|
|
10
|
+
"mp_*_api_host_override": { "company": "mParticle", "service": "mParticle SDK", "category": "tag_manager", "description": "mParticle API host override cookie for routing SDK calls through custom proxy endpoints", "consent_burden": "contested", "pattern": true, "lifetime": "session", "docs_url": "https://docs.mparticle.com/developers/sdk/web/configuration/" },
|
|
11
|
+
"rl_*": { "company": "RudderStack", "service": "RudderStack SDK", "category": "tag_manager", "description": "RudderStack open-source CDP cookie storing anonymous ID, user traits, and session data for tag routing", "consent_burden": "required", "pattern": true, "lifetime": "1 year", "docs_url": "https://www.rudderstack.com/privacy-policy/" },
|
|
12
|
+
"tdjs_*": { "company": "Treasure Data", "service": "Treasure Data JS SDK", "category": "tag_manager", "description": "Treasure Data CDP JavaScript SDK cookie for event collection and visitor identification", "consent_burden": "required", "pattern": true, "lifetime": "1 year", "docs_url": "https://www.treasuredata.com/privacy/" },
|
|
13
|
+
"tt_tealium_ct": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "description": "Tealium connection type cookie for tag management load rules", "consent_burden": "contested", "lifetime": "session", "docs_url": "https://docs.tealium.com/platforms/javascript/cookie-definitions/" },
|
|
14
|
+
"utag_main": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "description": "Primary Tealium visitor session cookie containing session ID and visit count", "consent_burden": "required", "lifetime": "1 year", "docs_url": "https://docs.tealium.com/platforms/javascript/cookie-definitions/" },
|
|
15
|
+
"utag_main_*": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "description": "Extended Tealium session data used for tag firing conditions and visitor stitching", "consent_burden": "required", "pattern": true, "lifetime": "1 year", "docs_url": "https://docs.tealium.com/platforms/javascript/cookie-definitions/" }
|
|
16
16
|
},
|
|
17
17
|
"domains": {
|
|
18
|
-
"api.lytics.io": { "company": "Lytics", "service": "Lytics API", "category": "tag_manager", "
|
|
19
|
-
"assets.adobedtm.com": { "company": "Adobe", "service": "Adobe Launch (DTM)", "category": "tag_manager", "
|
|
20
|
-
"cdn.actioniq.com": { "company": "ActionIQ", "service": "ActionIQ CDP Tag", "category": "tag_manager", "
|
|
21
|
-
"cdn.amperity.com": { "company": "Amperity", "service": "Amperity CDP Tag", "category": "tag_manager", "
|
|
22
|
-
"cdn.blueshift.com": { "company": "Blueshift", "service": "Blueshift CDP Tag", "category": "tag_manager", "
|
|
23
|
-
"cdn.census.com": { "company": "Census", "service": "Census Reverse ETL CDN", "category": "tag_manager", "
|
|
24
|
-
"cdn.commandersact.com/js": { "company": "Commanders Act", "service": "Commanders Act TagCommander", "category": "tag_manager", "
|
|
25
|
-
"cdn.exponea.com": { "company": "Bloomreach (Exponea)", "service": "Bloomreach CDP Tag", "category": "tag_manager", "
|
|
26
|
-
"cdn.freshpaint.io": { "company": "Freshpaint", "service": "Freshpaint Tag CDN", "category": "tag_manager", "
|
|
27
|
-
"cdn.hightouch.io": { "company": "Hightouch", "service": "Hightouch Events CDN", "category": "tag_manager", "
|
|
28
|
-
"cdn.lytics.io": { "company": "Lytics", "service": "Lytics CDP Tag", "category": "tag_manager", "
|
|
29
|
-
"cdn.mparticle.com": { "company": "mParticle", "service": "mParticle SDK CDN", "category": "tag_manager", "
|
|
30
|
-
"cdn.ometria.com": { "company": "Ometria", "service": "Ometria CDP Tag", "category": "tag_manager", "
|
|
31
|
-
"cdn.piwikpro.com": { "company": "Piwik PRO", "service": "Piwik PRO Tag Manager", "category": "tag_manager", "
|
|
32
|
-
"cdn.qubit.com": { "company": "Coveo/Qubit", "service": "Qubit Tag Manager", "category": "tag_manager", "
|
|
33
|
-
"cdn.rudderlabs.com": { "company": "RudderStack", "service": "RudderStack SDK CDN", "category": "tag_manager", "
|
|
34
|
-
"cdn.segment.com": { "company": "Twilio", "service": "Segment Tag Manager", "category": "tag_manager", "
|
|
35
|
-
"cdn.signal.co": { "company": "Signal (BrightTag)", "service": "Signal Tag Manager", "category": "tag_manager", "
|
|
36
|
-
"cdn.simondata.com": { "company": "Simon Data", "service": "Simon Data CDP Tag", "category": "tag_manager", "
|
|
37
|
-
"cdn.tagcommander.com": { "company": "Commanders Act", "service": "TagCommander", "category": "tag_manager", "
|
|
38
|
-
"cdn.treasuredata.com": { "company": "Treasure Data", "service": "Treasure Data CDP Tag", "category": "tag_manager", "
|
|
39
|
-
"cdn.zaius.com": { "company": "Optimizely (Zaius)", "service": "Zaius CDP Tag", "category": "tag_manager", "
|
|
40
|
-
"collect.tealiumiq.com": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "
|
|
41
|
-
"ensighten.com": { "company": "Ensighten", "service": "Ensighten Tag Manager", "category": "tag_manager", "
|
|
42
|
-
"googletagmanager.com": { "company": "Google", "service": "Google Tag Manager", "category": "tag_manager", "
|
|
43
|
-
"hs-scripts.com": { "company": "HubSpot", "service": "HubSpot Tracking Code (Regional CDN)", "category": "tag_manager", "
|
|
44
|
-
"identity.mparticle.com": { "company": "mParticle", "service": "mParticle Identity API", "category": "tag_manager", "
|
|
45
|
-
"js.hs-scripts.com": { "company": "HubSpot", "service": "HubSpot Tracking Code (Tag)", "category": "tag_manager", "
|
|
46
|
-
"jssdks.mparticle.com": { "company": "mParticle", "service": "mParticle JS SDK", "category": "tag_manager", "
|
|
47
|
-
"matomo.cloud": { "company": "Matomo", "service": "Matomo Tag Manager", "category": "tag_manager", "
|
|
48
|
-
"nexus.ensighten.com": { "company": "Ensighten", "service": "Ensighten Nexus", "category": "tag_manager", "
|
|
49
|
-
"tagmanager.google.com": { "company": "Google", "service": "Google Tag Manager", "category": "tag_manager", "
|
|
50
|
-
"tags.tiqcdn.com": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "
|
|
51
|
-
"www.googletagmanager.com": { "company": "Google", "service": "Google Tag Manager", "category": "tag_manager", "
|
|
18
|
+
"api.lytics.io": { "company": "Lytics", "service": "Lytics API", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.lytics.com/privacy/" },
|
|
19
|
+
"assets.adobedtm.com": { "company": "Adobe", "service": "Adobe Launch (DTM)", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://experienceleague.adobe.com/docs/experience-platform/tags/home.html" },
|
|
20
|
+
"cdn.actioniq.com": { "company": "ActionIQ", "service": "ActionIQ CDP Tag", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.actioniq.com/privacy-policy/" },
|
|
21
|
+
"cdn.amperity.com": { "company": "Amperity", "service": "Amperity CDP Tag", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://amperity.com/privacy/" },
|
|
22
|
+
"cdn.blueshift.com": { "company": "Blueshift", "service": "Blueshift CDP Tag", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://blueshift.com/privacy-policy/" },
|
|
23
|
+
"cdn.census.com": { "company": "Census", "service": "Census Reverse ETL CDN", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://www.getcensus.com/privacy" },
|
|
24
|
+
"cdn.commandersact.com/js": { "company": "Commanders Act", "service": "Commanders Act TagCommander", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://www.commandersact.com/en/privacy/" },
|
|
25
|
+
"cdn.exponea.com": { "company": "Bloomreach (Exponea)", "service": "Bloomreach CDP Tag", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.bloomreach.com/en/legal/privacy-policy" },
|
|
26
|
+
"cdn.freshpaint.io": { "company": "Freshpaint", "service": "Freshpaint Tag CDN", "category": "tag_manager", "consent_burden": "required", "note": "Healthcare-compliant analytics proxy that replaces direct third-party tag loading", "docs_url": "https://www.freshpaint.io/privacy-policy" },
|
|
27
|
+
"cdn.hightouch.io": { "company": "Hightouch", "service": "Hightouch Events CDN", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://hightouch.com/privacy-policy/" },
|
|
28
|
+
"cdn.lytics.io": { "company": "Lytics", "service": "Lytics CDP Tag", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.lytics.com/privacy/" },
|
|
29
|
+
"cdn.mparticle.com": { "company": "mParticle", "service": "mParticle SDK CDN", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.mparticle.com/privacy/" },
|
|
30
|
+
"cdn.ometria.com": { "company": "Ometria", "service": "Ometria CDP Tag", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://ometria.com/privacy-policy/" },
|
|
31
|
+
"cdn.piwikpro.com": { "company": "Piwik PRO", "service": "Piwik PRO Tag Manager", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://piwik.pro/privacy-policy/" },
|
|
32
|
+
"cdn.qubit.com": { "company": "Coveo/Qubit", "service": "Qubit Tag Manager", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://www.coveo.com/en/trust-center/privacy/privacy-notice" },
|
|
33
|
+
"cdn.rudderlabs.com": { "company": "RudderStack", "service": "RudderStack SDK CDN", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://www.rudderstack.com/privacy-policy/" },
|
|
34
|
+
"cdn.segment.com": { "company": "Twilio", "service": "Segment Tag Manager", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://segment.com/legal/privacy/" },
|
|
35
|
+
"cdn.signal.co": { "company": "Signal (BrightTag)", "service": "Signal Tag Manager", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://www.signal.co/privacy-policy/" },
|
|
36
|
+
"cdn.simondata.com": { "company": "Simon Data", "service": "Simon Data CDP Tag", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.simondata.com/privacy-policy/" },
|
|
37
|
+
"cdn.tagcommander.com": { "company": "Commanders Act", "service": "TagCommander", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://www.commandersact.com/en/privacy/" },
|
|
38
|
+
"cdn.treasuredata.com": { "company": "Treasure Data", "service": "Treasure Data CDP Tag", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.treasuredata.com/privacy/" },
|
|
39
|
+
"cdn.zaius.com": { "company": "Optimizely (Zaius)", "service": "Zaius CDP Tag", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.optimizely.com/legal/privacy-policy/" },
|
|
40
|
+
"collect.tealiumiq.com": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://docs.tealium.com/platforms/javascript/" },
|
|
41
|
+
"ensighten.com": { "company": "Ensighten", "service": "Ensighten Tag Manager", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://www.ensighten.com/privacy-policy/" },
|
|
42
|
+
"googletagmanager.com": { "company": "Google", "service": "Google Tag Manager", "category": "tag_manager", "consent_burden": "contested", "note": "Container script host; consent burden depends on tags loaded inside the container", "docs_url": "https://developers.google.com/tag-platform/tag-manager" },
|
|
43
|
+
"hs-scripts.com": { "company": "HubSpot", "service": "HubSpot Tracking Code (Regional CDN)", "category": "tag_manager", "consent_burden": "required", "note": "Umbrella catches regional variants (js-eu1, js-na1, js-au1, etc.)", "docs_url": "https://knowledge.hubspot.com/reports/what-cookies-does-hubspot-set-in-a-visitor-s-browser" },
|
|
44
|
+
"identity.mparticle.com": { "company": "mParticle", "service": "mParticle Identity API", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.mparticle.com/privacy/" },
|
|
45
|
+
"js.hs-scripts.com": { "company": "HubSpot", "service": "HubSpot Tracking Code (Tag)", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://knowledge.hubspot.com/reports/what-cookies-does-hubspot-set-in-a-visitor-s-browser" },
|
|
46
|
+
"jssdks.mparticle.com": { "company": "mParticle", "service": "mParticle JS SDK", "category": "tag_manager", "consent_burden": "required", "docs_url": "https://www.mparticle.com/privacy/" },
|
|
47
|
+
"matomo.cloud": { "company": "Matomo", "service": "Matomo Tag Manager", "category": "tag_manager", "consent_burden": "minimal", "docs_url": "https://matomo.org/docs/tag-manager/" },
|
|
48
|
+
"nexus.ensighten.com": { "company": "Ensighten", "service": "Ensighten Nexus", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://www.ensighten.com/privacy-policy/" },
|
|
49
|
+
"tagmanager.google.com": { "company": "Google", "service": "Google Tag Manager", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://developers.google.com/tag-platform/tag-manager" },
|
|
50
|
+
"tags.tiqcdn.com": { "company": "Tealium", "service": "Tealium iQ", "category": "tag_manager", "consent_burden": "contested", "docs_url": "https://docs.tealium.com/platforms/javascript/" },
|
|
51
|
+
"www.googletagmanager.com": { "company": "Google", "service": "Google Tag Manager", "category": "tag_manager", "consent_burden": "contested", "note": "Container script host; consent burden depends on tags loaded inside the container", "docs_url": "https://developers.google.com/tag-platform/tag-manager" }
|
|
52
52
|
}
|
|
53
53
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,27 +3,33 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The world's largest open-source GDPR tracker knowledge base.
|
|
5
5
|
* Every cookie, every domain, every actor on the web stage —
|
|
6
|
-
* identified,
|
|
6
|
+
* identified, categorised, and tagged with its consent burden.
|
|
7
|
+
*
|
|
8
|
+
* This library deliberately does **not** assign verdicts or scores. It
|
|
9
|
+
* gives you the facts about each tracker; what (if anything) you do with
|
|
10
|
+
* those facts is up to you. Consumers needing visualisation hierarchies
|
|
11
|
+
* (red / amber / green, "high risk", etc.) compute them in their own UI
|
|
12
|
+
* layer from the `consent_burden` and `category` fields.
|
|
7
13
|
*
|
|
8
14
|
* @example
|
|
9
15
|
* ```ts
|
|
10
|
-
* import { loadPlaybill, matchCookie
|
|
16
|
+
* import { loadPlaybill, matchCookie } from '@consenttheater/playbill';
|
|
11
17
|
*
|
|
12
|
-
* const playbill =
|
|
18
|
+
* const playbill = loadPlaybill('core');
|
|
13
19
|
* const actor = matchCookie(playbill, '_ga');
|
|
20
|
+
* // actor?.consent_burden === 'required'
|
|
14
21
|
* ```
|
|
15
22
|
*/
|
|
16
|
-
export type { Playbill, CookieActor, DomainActor, CookieMatch, DomainMatch, Tier,
|
|
23
|
+
export type { Playbill, CookieActor, DomainActor, CookieMatch, DomainMatch, Tier, ConsentBurden, Category } from './types.js';
|
|
17
24
|
export { matchCookie, matchDomain, isSameOrSubdomain, listCompanies, listCategories } from './matcher.js';
|
|
18
|
-
export { computeScore, bandForScore, SEVERITY_WEIGHTS, BANDS } from './scorer.js';
|
|
19
|
-
export type { ScoreInput, ObservedItem, ObservedBanner } from './scorer.js';
|
|
20
25
|
import type { Playbill, Tier } from './types.js';
|
|
21
26
|
/**
|
|
22
|
-
* Load a playbill tier by merging actor category files and filtering by
|
|
27
|
+
* Load a playbill tier by merging actor category files and filtering by
|
|
28
|
+
* consent burden.
|
|
23
29
|
*
|
|
24
|
-
* @param tier - 'mini' (~50 top companies,
|
|
25
|
-
* 'core' (all
|
|
26
|
-
* 'full' (everything)
|
|
30
|
+
* @param tier - 'mini' (~50 top companies, required_strict + required only),
|
|
31
|
+
* 'core' (all entries that require or might require consent),
|
|
32
|
+
* 'full' (everything, including minimal-burden entries)
|
|
27
33
|
*/
|
|
28
34
|
export declare function loadPlaybill(tier?: Tier): Playbill;
|
|
29
35
|
/**
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,YAAY,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,IAAI,EACJ,aAAa,EACb,QAAQ,EACT,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,cAAc,EACf,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAA2C,MAAM,YAAY,CAAC;AAiF1F;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,IAAa,GAAG,QAAQ,CAoB1D;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,QAAQ,CAgBzD"}
|
package/dist/index.js
CHANGED
|
@@ -3,18 +3,24 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The world's largest open-source GDPR tracker knowledge base.
|
|
5
5
|
* Every cookie, every domain, every actor on the web stage —
|
|
6
|
-
* identified,
|
|
6
|
+
* identified, categorised, and tagged with its consent burden.
|
|
7
|
+
*
|
|
8
|
+
* This library deliberately does **not** assign verdicts or scores. It
|
|
9
|
+
* gives you the facts about each tracker; what (if anything) you do with
|
|
10
|
+
* those facts is up to you. Consumers needing visualisation hierarchies
|
|
11
|
+
* (red / amber / green, "high risk", etc.) compute them in their own UI
|
|
12
|
+
* layer from the `consent_burden` and `category` fields.
|
|
7
13
|
*
|
|
8
14
|
* @example
|
|
9
15
|
* ```ts
|
|
10
|
-
* import { loadPlaybill, matchCookie
|
|
16
|
+
* import { loadPlaybill, matchCookie } from '@consenttheater/playbill';
|
|
11
17
|
*
|
|
12
|
-
* const playbill =
|
|
18
|
+
* const playbill = loadPlaybill('core');
|
|
13
19
|
* const actor = matchCookie(playbill, '_ga');
|
|
20
|
+
* // actor?.consent_burden === 'required'
|
|
14
21
|
* ```
|
|
15
22
|
*/
|
|
16
23
|
export { matchCookie, matchDomain, isSameOrSubdomain, listCompanies, listCategories } from './matcher.js';
|
|
17
|
-
export { computeScore, bandForScore, SEVERITY_WEIGHTS, BANDS } from './scorer.js';
|
|
18
24
|
// All actor category files
|
|
19
25
|
import advertising from './actors/advertising.json' with { type: 'json' };
|
|
20
26
|
import analytics from './actors/analytics.json' with { type: 'json' };
|
|
@@ -65,18 +71,20 @@ function filterEntries(entries, filterFn, topCompanies) {
|
|
|
65
71
|
}
|
|
66
72
|
return result;
|
|
67
73
|
}
|
|
74
|
+
const CONSENT_REQUIRED = ['required_strict', 'required', 'contested'];
|
|
68
75
|
const TIER_FILTERS = {
|
|
69
|
-
mini: (entry, topCompanies) => (entry.
|
|
76
|
+
mini: (entry, topCompanies) => (entry.consent_burden === 'required_strict' || entry.consent_burden === 'required') &&
|
|
70
77
|
topCompanies.has(entry.company),
|
|
71
|
-
core: (entry) =>
|
|
78
|
+
core: (entry) => CONSENT_REQUIRED.includes(entry.consent_burden),
|
|
72
79
|
full: () => true
|
|
73
80
|
};
|
|
74
81
|
/**
|
|
75
|
-
* Load a playbill tier by merging actor category files and filtering by
|
|
82
|
+
* Load a playbill tier by merging actor category files and filtering by
|
|
83
|
+
* consent burden.
|
|
76
84
|
*
|
|
77
|
-
* @param tier - 'mini' (~50 top companies,
|
|
78
|
-
* 'core' (all
|
|
79
|
-
* 'full' (everything)
|
|
85
|
+
* @param tier - 'mini' (~50 top companies, required_strict + required only),
|
|
86
|
+
* 'core' (all entries that require or might require consent),
|
|
87
|
+
* 'full' (everything, including minimal-burden entries)
|
|
80
88
|
*/
|
|
81
89
|
export function loadPlaybill(tier = 'full') {
|
|
82
90
|
const { cookies: allCookies, domains: allDomains } = mergeActors(ALL_ACTORS);
|
|
@@ -85,7 +93,7 @@ export function loadPlaybill(tier = 'full') {
|
|
|
85
93
|
const cookies = filterEntries(allCookies, filter, topCompanies);
|
|
86
94
|
const domains = filterEntries(allDomains, filter, topCompanies);
|
|
87
95
|
return {
|
|
88
|
-
version:
|
|
96
|
+
version: 3,
|
|
89
97
|
tier,
|
|
90
98
|
generated: new Date().toISOString(),
|
|
91
99
|
stats: {
|
|
@@ -109,7 +117,7 @@ export function loadActors(categories) {
|
|
|
109
117
|
const selected = ALL_ACTORS.filter(a => categories.includes(a.category));
|
|
110
118
|
const { cookies, domains } = mergeActors(selected);
|
|
111
119
|
return {
|
|
112
|
-
version:
|
|
120
|
+
version: 3,
|
|
113
121
|
tier: 'full',
|
|
114
122
|
generated: new Date().toISOString(),
|
|
115
123
|
stats: {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @consenttheater/playbill — Type definitions
|
|
3
3
|
*
|
|
4
|
-
* The Playbill is a theater program that lists every actor (tracker) and
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The Playbill is a theater program that lists every actor (tracker) and
|
|
5
|
+
* its role on the web stage. These types define the shape of that program.
|
|
6
|
+
*
|
|
7
|
+
* The library deliberately does **not** assign verdicts to whole websites
|
|
8
|
+
* or carry school-grade severity labels. It classifies trackers by the
|
|
9
|
+
* consent burden each one creates under EU/GDPR rules, leaves judgement
|
|
10
|
+
* to supervisory authorities and courts, and lets downstream consumers
|
|
11
|
+
* present the data however they like.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* How much explicit consent the tracker requires under GDPR / ePrivacy.
|
|
15
|
+
*
|
|
16
|
+
* - `required_strict` — Cross-site profiling, ad-tech retargeting,
|
|
17
|
+
* fingerprinting, session recording. Always needs prior, informed,
|
|
18
|
+
* freely-given consent.
|
|
19
|
+
* - `required` — Standard analytics and marketing tracking.
|
|
20
|
+
* Consent required in nearly all interpretations.
|
|
21
|
+
* - `contested` — Tracking-adjacent or jurisdiction-dependent.
|
|
22
|
+
* Some authorities allow under legitimate interest, others require
|
|
23
|
+
* consent. Treat as consent-required by default.
|
|
24
|
+
* - `minimal` — Functional, security, or strictly-necessary in
|
|
25
|
+
* most interpretations. Often exempt from consent requirements.
|
|
7
26
|
*/
|
|
8
|
-
export type
|
|
27
|
+
export type ConsentBurden = 'required_strict' | 'required' | 'contested' | 'minimal';
|
|
9
28
|
export type Category = 'advertising' | 'analytics' | 'marketing' | 'functional' | 'tag_manager' | 'data_leak' | 'social' | 'session_recording' | 'security' | 'consent' | 'fingerprinting';
|
|
10
29
|
export type Tier = 'mini' | 'core' | 'full';
|
|
11
30
|
/** A cookie actor in the playbill — a known tracking cookie signature. */
|
|
@@ -14,7 +33,7 @@ export interface CookieActor {
|
|
|
14
33
|
service: string;
|
|
15
34
|
category: Category;
|
|
16
35
|
description?: string;
|
|
17
|
-
|
|
36
|
+
consent_burden: ConsentBurden;
|
|
18
37
|
pattern?: boolean;
|
|
19
38
|
note?: string;
|
|
20
39
|
lifetime?: string;
|
|
@@ -25,7 +44,7 @@ export interface DomainActor {
|
|
|
25
44
|
company: string;
|
|
26
45
|
service: string;
|
|
27
46
|
category: Category;
|
|
28
|
-
|
|
47
|
+
consent_burden: ConsentBurden;
|
|
29
48
|
note?: string;
|
|
30
49
|
docs_url?: string;
|
|
31
50
|
}
|
|
@@ -52,27 +71,4 @@ export interface DomainMatch extends DomainActor {
|
|
|
52
71
|
hostname: string;
|
|
53
72
|
matchedDomain?: string;
|
|
54
73
|
}
|
|
55
|
-
/** Risk band derived from the compliance score. */
|
|
56
|
-
export type BandKey = 'compliant' | 'at_risk' | 'non_compliant' | 'violating';
|
|
57
|
-
export interface Band {
|
|
58
|
-
key: BandKey;
|
|
59
|
-
label: string;
|
|
60
|
-
}
|
|
61
|
-
export interface Violation {
|
|
62
|
-
type: string;
|
|
63
|
-
severity: Severity;
|
|
64
|
-
count: number;
|
|
65
|
-
description: string;
|
|
66
|
-
items?: Array<{
|
|
67
|
-
name?: string;
|
|
68
|
-
hostname?: string;
|
|
69
|
-
company?: string;
|
|
70
|
-
note?: string;
|
|
71
|
-
}>;
|
|
72
|
-
}
|
|
73
|
-
export interface ScoreResult {
|
|
74
|
-
score: number;
|
|
75
|
-
band: Band;
|
|
76
|
-
violations: Violation[];
|
|
77
|
-
}
|
|
78
74
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,aAAa,GACrB,iBAAiB,GACjB,UAAU,GACV,WAAW,GACX,SAAS,CAAC;AAEd,MAAM,MAAM,QAAQ,GAChB,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,GACxD,aAAa,GAAG,WAAW,GAAG,QAAQ,GAAG,mBAAmB,GAC5D,UAAU,GAAG,SAAS,GAAG,gBAAgB,CAAC;AAE9C,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,aAAa,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,aAAa,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,0DAA0D;AAC1D,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACtC;AAED,6DAA6D;AAC7D,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wDAAwD;AACxD,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
|
package/dist/types.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @consenttheater/playbill — Type definitions
|
|
3
3
|
*
|
|
4
|
-
* The Playbill is a theater program that lists every actor (tracker) and
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The Playbill is a theater program that lists every actor (tracker) and
|
|
5
|
+
* its role on the web stage. These types define the shape of that program.
|
|
6
|
+
*
|
|
7
|
+
* The library deliberately does **not** assign verdicts to whole websites
|
|
8
|
+
* or carry school-grade severity labels. It classifies trackers by the
|
|
9
|
+
* consent burden each one creates under EU/GDPR rules, leaves judgement
|
|
10
|
+
* to supervisory authorities and courts, and lets downstream consumers
|
|
11
|
+
* present the data however they like.
|
|
7
12
|
*/
|
|
8
13
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@consenttheater/playbill",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "An open-source, tiered knowledge base of GDPR-relevant web trackers (cookies, domains, companies) with pure-function matching
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "An open-source, tiered knowledge base of GDPR-relevant web trackers (cookies, domains, companies) with pure-function matching helpers. Each entry is tagged with the consent burden it creates under EU/GDPR rules — no verdicts, no risk scores. Standalone library for privacy auditors, compliance scanners, consent platforms, browser extensions, and research tools.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "ConsentTheater",
|
|
7
7
|
"email": "developer@consenttheater.org",
|
|
@@ -50,10 +50,6 @@
|
|
|
50
50
|
"import": "./dist/matcher.js",
|
|
51
51
|
"types": "./dist/matcher.d.ts"
|
|
52
52
|
},
|
|
53
|
-
"./scorer": {
|
|
54
|
-
"import": "./dist/scorer.js",
|
|
55
|
-
"types": "./dist/scorer.d.ts"
|
|
56
|
-
},
|
|
57
53
|
"./types": {
|
|
58
54
|
"types": "./dist/types.d.ts"
|
|
59
55
|
}
|
|
@@ -71,7 +67,7 @@
|
|
|
71
67
|
},
|
|
72
68
|
"devDependencies": {
|
|
73
69
|
"typescript": "^5.9.3",
|
|
74
|
-
"vitest": "^4.1.
|
|
70
|
+
"vitest": "^4.1.5"
|
|
75
71
|
},
|
|
76
72
|
"engines": {
|
|
77
73
|
"node": ">=22.0.0"
|
package/dist/scorer.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @consenttheater/playbill — Scorer
|
|
3
|
-
*
|
|
4
|
-
* Risk scoring — pure functions. Given observations (cookies, requests, banner),
|
|
5
|
-
* produce a compliance score with risk band and violation list.
|
|
6
|
-
*
|
|
7
|
-
* Bands: >= 90 Compliant, 70-89 At Risk, 40-69 Non-Compliant, < 40 Violating
|
|
8
|
-
* Weights: critical -25, high -15, medium -10, low -5
|
|
9
|
-
*/
|
|
10
|
-
import type { Severity, Band, BandKey, ScoreResult } from './types.js';
|
|
11
|
-
export declare const SEVERITY_WEIGHTS: Record<Severity, number>;
|
|
12
|
-
export declare const BANDS: readonly {
|
|
13
|
-
min: number;
|
|
14
|
-
key: BandKey;
|
|
15
|
-
label: string;
|
|
16
|
-
}[];
|
|
17
|
-
export declare function bandForScore(score: number): Band;
|
|
18
|
-
export interface ObservedItem {
|
|
19
|
-
name?: string;
|
|
20
|
-
hostname?: string;
|
|
21
|
-
company?: string;
|
|
22
|
-
service?: string;
|
|
23
|
-
severity: Severity;
|
|
24
|
-
category?: string;
|
|
25
|
-
note?: string;
|
|
26
|
-
}
|
|
27
|
-
export interface ObservedBanner {
|
|
28
|
-
detected: boolean;
|
|
29
|
-
hasAcceptButton?: boolean;
|
|
30
|
-
hasRejectButton?: boolean;
|
|
31
|
-
hasManageButton?: boolean;
|
|
32
|
-
buttonCount?: number;
|
|
33
|
-
textPreview?: string;
|
|
34
|
-
}
|
|
35
|
-
export interface ScoreInput {
|
|
36
|
-
preConsentCookies?: ObservedItem[];
|
|
37
|
-
preConsentRequests?: ObservedItem[];
|
|
38
|
-
dataLeakRequests?: ObservedItem[];
|
|
39
|
-
banner?: ObservedBanner | null;
|
|
40
|
-
}
|
|
41
|
-
export declare function computeScore(input: ScoreInput): ScoreResult;
|
|
42
|
-
//# sourceMappingURL=scorer.d.ts.map
|
package/dist/scorer.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../src/scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAa,MAAM,YAAY,CAAC;AAElF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAKrD,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,SAAS;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAKxE,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAKhD;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,iBAAiB,CAAC,EAAE,YAAY,EAAE,CAAC;IACnC,kBAAkB,CAAC,EAAE,YAAY,EAAE,CAAC;IACpC,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC;IAClC,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CAChC;AAUD,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAwE3D"}
|
package/dist/scorer.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
export const SEVERITY_WEIGHTS = {
|
|
2
|
-
critical: 25,
|
|
3
|
-
high: 15,
|
|
4
|
-
medium: 10,
|
|
5
|
-
low: 5
|
|
6
|
-
};
|
|
7
|
-
export const BANDS = [
|
|
8
|
-
{ min: 90, key: 'compliant', label: 'Compliant' },
|
|
9
|
-
{ min: 70, key: 'at_risk', label: 'At Risk' },
|
|
10
|
-
{ min: 40, key: 'non_compliant', label: 'Non-Compliant' },
|
|
11
|
-
{ min: 0, key: 'violating', label: 'Violating' }
|
|
12
|
-
];
|
|
13
|
-
export function bandForScore(score) {
|
|
14
|
-
for (const b of BANDS) {
|
|
15
|
-
if (score >= b.min)
|
|
16
|
-
return { key: b.key, label: b.label };
|
|
17
|
-
}
|
|
18
|
-
return { key: 'violating', label: 'Violating' };
|
|
19
|
-
}
|
|
20
|
-
function bucketBySeverity(items) {
|
|
21
|
-
const out = { critical: [], high: [], medium: [], low: [] };
|
|
22
|
-
for (const it of items || []) {
|
|
23
|
-
if (out[it.severity])
|
|
24
|
-
out[it.severity].push(it);
|
|
25
|
-
}
|
|
26
|
-
return out;
|
|
27
|
-
}
|
|
28
|
-
export function computeScore(input) {
|
|
29
|
-
const violations = [];
|
|
30
|
-
const cookies = bucketBySeverity(input.preConsentCookies);
|
|
31
|
-
const reqs = bucketBySeverity(input.preConsentRequests);
|
|
32
|
-
if (cookies.critical.length) {
|
|
33
|
-
violations.push({
|
|
34
|
-
type: 'critical_cookies_before_consent', severity: 'critical', count: cookies.critical.length,
|
|
35
|
-
description: `${cookies.critical.length} advertising/tracking cookie(s) set before consent`,
|
|
36
|
-
items: cookies.critical.map(c => ({ name: c.name, company: c.company }))
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
if (cookies.high.length) {
|
|
40
|
-
violations.push({
|
|
41
|
-
type: 'high_cookies_before_consent', severity: 'high', count: cookies.high.length,
|
|
42
|
-
description: `${cookies.high.length} analytics cookie(s) set before consent`,
|
|
43
|
-
items: cookies.high.map(c => ({ name: c.name, company: c.company }))
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
if (cookies.medium.length) {
|
|
47
|
-
violations.push({
|
|
48
|
-
type: 'medium_cookies_before_consent', severity: 'medium', count: cookies.medium.length,
|
|
49
|
-
description: `${cookies.medium.length} tracking cookie(s) set before consent`,
|
|
50
|
-
items: cookies.medium.map(c => ({ name: c.name, company: c.company }))
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
if (reqs.critical.length) {
|
|
54
|
-
violations.push({
|
|
55
|
-
type: 'critical_requests_before_consent', severity: 'critical', count: reqs.critical.length,
|
|
56
|
-
description: `${reqs.critical.length} advertising request(s) fired before consent`,
|
|
57
|
-
items: reqs.critical.map(r => ({ hostname: r.hostname, company: r.company }))
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
if (reqs.high.length) {
|
|
61
|
-
violations.push({
|
|
62
|
-
type: 'high_requests_before_consent', severity: 'high', count: reqs.high.length,
|
|
63
|
-
description: `${reqs.high.length} analytics request(s) fired before consent`,
|
|
64
|
-
items: reqs.high.map(r => ({ hostname: r.hostname, company: r.company }))
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
const leaks = (input.dataLeakRequests || []).filter(r => r.category === 'data_leak');
|
|
68
|
-
if (leaks.length) {
|
|
69
|
-
violations.push({
|
|
70
|
-
type: 'data_leaks', severity: 'medium', count: leaks.length,
|
|
71
|
-
description: `${leaks.length} data-leak request(s) (IP exposure to third parties)`,
|
|
72
|
-
items: leaks.map(r => ({ hostname: r.hostname, company: r.company, note: r.note }))
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
const banner = input.banner;
|
|
76
|
-
if (banner?.detected) {
|
|
77
|
-
if (banner.hasAcceptButton && !banner.hasRejectButton) {
|
|
78
|
-
violations.push({
|
|
79
|
-
type: 'banner_missing_reject', severity: 'high', count: 1,
|
|
80
|
-
description: 'Consent banner has Accept but no Reject/Decline option'
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
else if (banner === null || (banner && !banner.detected)) {
|
|
85
|
-
if ((input.preConsentCookies || []).length || (input.preConsentRequests || []).length) {
|
|
86
|
-
violations.push({
|
|
87
|
-
type: 'no_banner_with_trackers', severity: 'high', count: 1,
|
|
88
|
-
description: 'No consent banner detected but trackers are present'
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
let score = 100;
|
|
93
|
-
for (const v of violations)
|
|
94
|
-
score -= (SEVERITY_WEIGHTS[v.severity] || 0);
|
|
95
|
-
score = Math.max(0, Math.min(100, score));
|
|
96
|
-
return { score, band: bandForScore(score), violations };
|
|
97
|
-
}
|