@tantainnovative/ndpr-toolkit 5.5.0 → 5.6.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/CHANGELOG.md +41 -0
- package/README.md +25 -0
- package/dist/chunk-675DXBED.mjs +1 -0
- package/dist/{chunk-QKXGVT2Q.js → chunk-GJH7YFBO.js} +1 -1
- package/dist/chunk-H3Q3I6XC.js +1 -0
- package/dist/{chunk-XCKX2WKD.js → chunk-HCZDQWHY.js} +1 -1
- package/dist/chunk-LAAJVTUV.mjs +1 -0
- package/dist/{chunk-JXK5RUR3.mjs → chunk-ME77GU4Q.mjs} +1 -1
- package/dist/chunk-MGXWQW5I.mjs +1 -0
- package/dist/chunk-VFRGCBJY.js +1 -0
- package/dist/{chunk-PQ5IPUJN.mjs → chunk-VXLOPB33.mjs} +1 -1
- package/dist/chunk-ZVWSSXV2.js +1 -0
- package/dist/consent.d.mts +88 -0
- package/dist/consent.d.ts +88 -0
- package/dist/consent.js +1 -1
- package/dist/consent.mjs +1 -1
- package/dist/core.d.mts +88 -0
- package/dist/core.d.ts +88 -0
- package/dist/core.js +1 -1
- package/dist/core.mjs +1 -1
- package/dist/headless.d.mts +163 -0
- package/dist/headless.d.ts +163 -0
- package/dist/headless.js +1 -1
- package/dist/headless.mjs +1 -1
- package/dist/hooks.d.mts +90 -0
- package/dist/hooks.d.ts +90 -0
- package/dist/hooks.js +1 -1
- package/dist/hooks.mjs +1 -1
- package/dist/index.d.mts +105 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/server.d.mts +88 -0
- package/dist/server.d.ts +88 -0
- package/dist/server.js +1 -1
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-DKLJ5DYN.js +0 -1
- package/dist/chunk-OW4GO3JF.js +0 -1
- package/dist/chunk-Q5KB2DN3.mjs +0 -1
- package/dist/chunk-R3ZKV2J7.mjs +0 -1
- package/dist/chunk-SZXHNJGG.mjs +0 -1
- package/dist/chunk-WKY26JLT.js +0 -1
- /package/dist/{chunk-YQTZWPOS.mjs → chunk-23CULZBM.mjs} +0 -0
- /package/dist/{chunk-OVW5ASY3.js → chunk-VKDW2IHV.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,47 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [5.6.0](https://github.com/mr-tanta/ndpr-toolkit/compare/v5.5.1...v5.6.0) (2026-06-01)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **consent:** add cookie scanner (declared vs present audit) ([d74366f](https://github.com/mr-tanta/ndpr-toolkit/commit/d74366f8356857621a94729eb79225cdfbef2024))
|
|
11
|
+
* **packages:** refresh create-ndpr and ndpr-recipes for GAID 2025 ([bf709cf](https://github.com/mr-tanta/ndpr-toolkit/commit/bf709cf4f40176e65f21f2db61a946542fac7479))
|
|
12
|
+
* **site:** make the /score audit a full-screen cinematic experience ([52cc0e8](https://github.com/mr-tanta/ndpr-toolkit/commit/52cc0e8b6b889df0ca6c1842a71d25029f4e4aaa))
|
|
13
|
+
* **site:** turn the /score audit into a guided step-by-step wizard ([18f26ad](https://github.com/mr-tanta/ndpr-toolkit/commit/18f26ad36726f4b3ef9228e032e3d60eb4de1786))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* **packages:** use canonical bin path (no ./ prefix) in create-ndpr manifests ([600d989](https://github.com/mr-tanta/ndpr-toolkit/commit/600d989f1f73fe5174f4d3fc035980bfa6c8fa27))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Documentation
|
|
22
|
+
|
|
23
|
+
* **marketing:** refresh the X thread + LinkedIn post for current state ([58c6fca](https://github.com/mr-tanta/ndpr-toolkit/commit/58c6fca46899765bf3a09eee5cc0fca387f6cd99))
|
|
24
|
+
* **site:** add Cookie Scanner guide page ([5813686](https://github.com/mr-tanta/ndpr-toolkit/commit/58136865de16e9f1f8b74c7918294fdcd0c5b78f))
|
|
25
|
+
|
|
26
|
+
## [5.5.1](https://github.com/mr-tanta/ndpr-toolkit/compare/v5.5.0...v5.5.1) (2026-05-31)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Features
|
|
30
|
+
|
|
31
|
+
* **site:** cross-link the ndpr audit CLI from the score and DPIA marketing pages ([ca35869](https://github.com/mr-tanta/ndpr-toolkit/commit/ca358690d0817363a5b8c65513c61a02152068e4))
|
|
32
|
+
* **site:** surface the GAID 2025 layer and ndpr audit CLI on the landing page ([e84ea43](https://github.com/mr-tanta/ndpr-toolkit/commit/e84ea43232f23c5baba4bddeba224f9f9ab8ebaf))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* **dcpmi:** only UHL and EHL file CAR; OHL renews registration annually ([07a7bc6](https://github.com/mr-tanta/ndpr-toolkit/commit/07a7bc6e7f4d13d960a9fc5f008429834a583359))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
### Documentation
|
|
41
|
+
|
|
42
|
+
* **blog:** add four NDPC GAID 2025 articles ([0b25725](https://github.com/mr-tanta/ndpr-toolkit/commit/0b25725c871b1e72baada1113ca919fcdaae47f9))
|
|
43
|
+
* correct DCPMI registration fees and the OHL CAR rule ([b1f8ed4](https://github.com/mr-tanta/ndpr-toolkit/commit/b1f8ed4a03feef086730bf1f26902addb069951e))
|
|
44
|
+
* link the audit CLI guide from the backend integration guide ([4dfaab7](https://github.com/mr-tanta/ndpr-toolkit/commit/4dfaab7b908b44b756c8411dd8d809bf598e0390))
|
|
45
|
+
|
|
5
46
|
## [5.5.0](https://github.com/mr-tanta/ndpr-toolkit/compare/v5.4.0...v5.5.0) (2026-05-31)
|
|
6
47
|
|
|
7
48
|
|
package/README.md
CHANGED
|
@@ -536,6 +536,31 @@ The content checklist (`notificationToCommission`) maps each item to its source
|
|
|
536
536
|
|
|
537
537
|
---
|
|
538
538
|
|
|
539
|
+
## Cookie Scanner
|
|
540
|
+
|
|
541
|
+
`scanCookies()` audits the cookies **actually present** against the cookies you've **declared**, surfacing undeclared cookies that put you out of step with your cookie notice (**NDPA 2023 S.25–26** / **NDPC GAID 2025** — consent must be specific and informed). It's pure and DOM-optional: pass a `cookieString` (a `Cookie:` header server-side, or a fixture) or let it read `document.cookie` in the browser.
|
|
542
|
+
|
|
543
|
+
```ts
|
|
544
|
+
import { scanCookies } from '@tantainnovative/ndpr-toolkit/core'; // or /server
|
|
545
|
+
|
|
546
|
+
const scan = scanCookies(
|
|
547
|
+
[{ name: 'sid', category: 'necessary', provider: 'App', purpose: 'Login session' }],
|
|
548
|
+
{ cookieString: document.cookie }, // omit in the browser to read it automatically
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
scan.complete; // false while any undeclared cookie is present
|
|
552
|
+
scan.undeclared; // cookies on the page you didn't declare — the compliance gap
|
|
553
|
+
scan.identified; // undeclared, but the built-in registry knows them (_ga → Google Analytics, …)
|
|
554
|
+
scan.unknown; // undeclared and unidentifiable
|
|
555
|
+
scan.byCategory; // present cookies grouped by resolved category
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
A built-in `KNOWN_COOKIES` registry recognises common third-party cookies (Google Analytics/Ads, Meta, Hotjar, Microsoft Clarity, LinkedIn, Stripe, HubSpot, TikTok, Intercom, …) so even undeclared cookies are usually identified with a provider and likely category; extend it via `knownCookies` or disable it with `useKnownRegistry: false`. Your own declarations always take precedence. Also available as the client-side `useCookieScan(declared?, options?)` hook from `/hooks`, which scans on mount and returns a stable `rescan()`.
|
|
559
|
+
|
|
560
|
+
> A compliance-discovery aid, not legal advice — verify against current NDPC guidance.
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
539
564
|
## Compliance Audit CLI
|
|
540
565
|
|
|
541
566
|
The package ships an `ndpr` binary. `ndpr audit` scores a compliance config against the toolkit's engine — the compliance score plus the GAID 2025 DCPMI, CAR, and breach-notification checks — and **exits non-zero when the audit fails**, so you can drop it into CI as a compliance gate.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function S(r){let e=[];if((!r.consents||Object.keys(r.consents).length===0)&&e.push({field:"consents",code:"consents_required",message:"Consent settings must include at least one consent option"}),r.timestamp?(typeof r.timestamp!="number"||isNaN(r.timestamp))&&e.push({field:"timestamp",code:"timestamp_invalid",message:"Consent timestamp must be a valid number"}):e.push({field:"timestamp",code:"timestamp_required",message:"Consent timestamp is required"}),r.version||e.push({field:"version",code:"version_required",message:"Consent version is required"}),r.method||e.push({field:"method",code:"method_required",message:"Consent collection method is required"}),r.hasInteracted===void 0&&e.push({field:"hasInteracted",code:"has_interacted_required",message:"User interaction status is required"}),r.timestamp){let o=new Date;o.setMonth(o.getMonth()-13);let n=o.getTime();r.timestamp<n&&e.push({field:"timestamp",code:"consent_stale",message:"Consent is older than 13 months and should be refreshed"});}return e.length>0?{valid:false,errors:e}:{valid:true,errors:[],data:r}}function b(r){let e=[];return (!r||r.length===0)&&e.push({field:"options",code:"options_required",message:"At least one consent option is required"}),r==null||r.forEach((o,n)=>{(!o.purpose||o.purpose.trim()==="")&&e.push({field:`options[${n}].purpose`,code:"purpose_required",message:`Consent option "${o.id}" is missing a purpose. NDPA Section 26 requires consent to be specific to a stated purpose.`});}),e.length>0?{valid:false,errors:e}:{valid:true,errors:[],data:r}}var v=[{name:"_ga",category:"analytics",provider:"Google Analytics",purpose:"Distinguishes users"},{name:"_ga_",prefix:true,category:"analytics",provider:"Google Analytics (GA4)",purpose:"Persists session state"},{name:"_gid",category:"analytics",provider:"Google Analytics",purpose:"Distinguishes users"},{name:"_gat",prefix:true,category:"analytics",provider:"Google Analytics",purpose:"Throttles request rate"},{name:"_dc_gtm_",prefix:true,category:"analytics",provider:"Google Tag Manager",purpose:"Throttles request rate"},{name:"_gcl_",prefix:true,category:"marketing",provider:"Google Ads",purpose:"Conversion tracking"},{name:"IDE",category:"marketing",provider:"Google DoubleClick",purpose:"Ad targeting"},{name:"test_cookie",category:"marketing",provider:"Google DoubleClick",purpose:"Checks cookie support"},{name:"_fbp",category:"marketing",provider:"Meta (Facebook)",purpose:"Ad delivery and measurement"},{name:"_fbc",category:"marketing",provider:"Meta (Facebook)",purpose:"Click attribution"},{name:"fr",category:"marketing",provider:"Meta (Facebook)",purpose:"Ad delivery and measurement"},{name:"_clck",category:"analytics",provider:"Microsoft Clarity",purpose:"Session analytics"},{name:"_clsk",category:"analytics",provider:"Microsoft Clarity",purpose:"Session analytics"},{name:"_hj",prefix:true,category:"analytics",provider:"Hotjar",purpose:"Behaviour analytics"},{name:"bcookie",category:"marketing",provider:"LinkedIn",purpose:"Browser identification"},{name:"lidc",category:"marketing",provider:"LinkedIn",purpose:"Routing / ad delivery"},{name:"li_",prefix:true,category:"marketing",provider:"LinkedIn",purpose:"Ad delivery"},{name:"_ttp",category:"marketing",provider:"TikTok",purpose:"Ad measurement"},{name:"personalization_id",category:"marketing",provider:"X (Twitter)",purpose:"Ad personalisation"},{name:"guest_id",category:"marketing",provider:"X (Twitter)",purpose:"Identifies the browser"},{name:"hubspotutk",category:"marketing",provider:"HubSpot",purpose:"Visitor identification"},{name:"__hs",prefix:true,category:"analytics",provider:"HubSpot",purpose:"Analytics / session"},{name:"__stripe_mid",category:"necessary",provider:"Stripe",purpose:"Fraud prevention"},{name:"__stripe_sid",category:"necessary",provider:"Stripe",purpose:"Fraud prevention"},{name:"intercom-",prefix:true,category:"functional",provider:"Intercom",purpose:"Live chat / messaging"},{name:"ndpr_consent",category:"necessary",provider:"NDPR Toolkit",purpose:"Stores the consent decision"}];function k(r,e){return e.name instanceof RegExp?e.name.test(r):e.prefix?r.startsWith(e.name):r===e.name}function C(r){return r.split(";").map(e=>{let o=e.trim(),n=o.indexOf("=");return (n===-1?o:o.slice(0,n)).trim()}).filter(e=>e.length>0)}function A(r=[],e={}){var u,l,m,g,f,y;let o=(u=e.cookieString)!=null?u:typeof document!="undefined"?document.cookie:"",n=(l=e.asOf)!=null?l:Date.now(),h=((m=e.useKnownRegistry)!=null?m:true)?[...(g=e.knownCookies)!=null?g:[],...v]:[],a=C(o).map(t=>{let i=r.find(d=>k(t,d));if(i)return {name:t,category:i.category,matchedBy:"declared",provider:i.provider,purpose:i.purpose};let c=h.find(d=>k(t,d));return c?{name:t,category:c.category,matchedBy:"known",provider:c.provider,purpose:c.purpose}:{name:t,category:null,matchedBy:"none"}}),s={};for(let t of a){let i=(f=t.category)!=null?f:"uncategorized";((y=s[i])!=null?y:s[i]=[]).push(t);}let p=a.filter(t=>t.matchedBy!=="declared");return {scannedAt:n,total:a.length,cookies:a,declared:a.filter(t=>t.matchedBy==="declared"),undeclared:p,identified:a.filter(t=>t.matchedBy==="known"),unknown:a.filter(t=>t.matchedBy==="none"),byCategory:s,complete:p.length===0}}export{S as a,b,v as c,A as d};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var chunkC2KEXHRX_js=require('./chunk-C2KEXHRX.js'),
|
|
1
|
+
'use strict';var chunkC2KEXHRX_js=require('./chunk-C2KEXHRX.js'),chunkZVWSSXV2_js=require('./chunk-ZVWSSXV2.js'),chunkVWED6UTN_js=require('./chunk-VWED6UTN.js'),react=require('react');function F(o){if(!o)return chunkVWED6UTN_js.a("ndpr_consent");let{storageKey:n="ndpr_consent",storageType:i="localStorage"}=o;return i==="sessionStorage"?chunkC2KEXHRX_js.a(n):i==="cookie"?chunkC2KEXHRX_js.b(n,o.cookieOptions):chunkVWED6UTN_js.a(n)}function V(o,n,i,r,a,p,l){if(o){i(o);let{valid:s,errors:c}=chunkZVWSSXV2_js.a(o);r(s),a(c),p(!(s&&o.version===n));}else p(true);l(false);}function z({options:o,adapter:n,storageOptions:i,version:r="1.0",onChange:a}){let p=n!=null?n:F(i),l=react.useRef(p);l.current=p;let[s,c]=react.useState(null),[y,d]=react.useState(false),[O,S]=react.useState(false),[k,C]=react.useState([]),[w,v]=react.useState(true);react.useEffect(()=>{let t=false;try{let e=l.current.load();e instanceof Promise?e.then(m=>{t||V(m,r,c,S,C,d,v);},()=>{t||(d(!0),v(!1));}):V(e,r,c,S,C,d,v);}catch(e){t||(d(true),v(false));}return ()=>{t=true;}},[r]);let h=react.useCallback(t=>{let{valid:e,errors:m}=chunkZVWSSXV2_js.a(t);S(e),C(m),a==null||a(t),Promise.resolve(l.current.save(t)).catch(j=>{console.warn("[ndpr-toolkit] Failed to save consent:",j);});},[a]),f=react.useCallback(t=>{let e={consents:t,timestamp:Date.now(),version:r,method:"explicit",hasInteracted:true};c(e),h(e),d(false);},[r,h]),x=react.useCallback(()=>{let t={};o.forEach(e=>{t[e.id]=true;}),f(t);},[o,f]),I=react.useCallback(()=>{let t={};o.forEach(e=>{t[e.id]=e.required||false;}),f(t);},[o,f]),L=react.useCallback(t=>!!(s!=null&&s.consents[t]),[s]),U=react.useCallback(()=>{c(null),d(true),S(false),C([]),Promise.resolve(l.current.remove()).catch(t=>{console.warn("[ndpr-toolkit] Failed to remove consent:",t);});},[]);return {settings:s,hasConsent:L,updateConsent:f,acceptAll:x,rejectAll:I,shouldShowBanner:y,isValid:O,validationErrors:k,resetConsent:U,isLoading:w}}exports.a=z;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var chunkVFRGCBJY_js=require('./chunk-VFRGCBJY.js'),chunk7TTXS7JX_js=require('./chunk-7TTXS7JX.js'),chunkY346CURW_js=require('./chunk-Y346CURW.js'),chunkZVWSSXV2_js=require('./chunk-ZVWSSXV2.js'),react=require('react');function h(e,o){return react.useMemo(()=>chunkY346CURW_js.a(e,o),[e,o])}function x({input:e}){let o=JSON.stringify(e);return react.useMemo(()=>chunk7TTXS7JX_js.a(e),[o])}function b(e,o){return react.useMemo(()=>chunkVFRGCBJY_js.c(e,o),[e.dataSubjectsInSixMonths,e.isDesignated,o])}function v(e,o){let[u,f]=react.useState(null),i=react.useRef(e),r=react.useRef(o);i.current=e,r.current=o;let t=react.useCallback(()=>{f(chunkZVWSSXV2_js.d(i.current,r.current));},[]);return react.useEffect(()=>{t();},[t]),{result:u,rescan:t}}function q(e,o){return react.useMemo(()=>chunkVFRGCBJY_js.d(e,o),[e.commencementDate,e.asOf,e.tier,o])}exports.a=h;exports.b=x;exports.c=b;exports.d=v;exports.e=q;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var chunkVFRGCBJY_js=require('./chunk-VFRGCBJY.js'),chunk7TTXS7JX_js=require('./chunk-7TTXS7JX.js'),chunkY346CURW_js=require('./chunk-Y346CURW.js');var b=e=>`\u20A6${e.toLocaleString("en-NG")}`;function P(e,c={}){var m,u;let r=(m=c.minScore)!=null?m:70,i=chunk7TTXS7JX_js.a(e.compliance),a=[];a.push({id:"compliance-score",label:"Overall compliance score",status:i.score>=r?"pass":"fail",detail:`${i.score}/100 (${i.rating}); minimum ${r}.`});for(let t of i.recommendations)t.priority!=="critical"&&t.priority!=="high"||a.push({id:`gap:${t.module}:${t.key}`,label:`${t.label} (${t.ndpaSection})`,status:t.priority==="critical"?"fail":"warn",detail:t.recommendation});let n;e.dcpmi&&(n=chunkVFRGCBJY_js.c(e.dcpmi,c.dcpmiOptions),a.push({id:"dcpmi",label:"DCPMI registration (GAID 2025)",status:n.tier==="listed"?"warn":"pass",detail:n.isDCPMI?`${n.tier} \u2014 ${b(n.annualFeeNGN)}/yr; ${n.registration.renewsAnnually?"renew registration annually":"register once + file CAR annually"}.`:"Not a Data Controller/Processor of Major Importance by volume."}));let s;if(e.car){s=chunkVFRGCBJY_js.d(e.car,c.carOptions);let t=s.status.daysUntilNextDeadline;a.push({id:"car",label:"Compliance Audit Returns (NDPC GAID 2025)",status:s.applicable&&(s.status.initialAuditDue||t<=30)?"warn":"pass",detail:s.applicable?`Next filing ${s.schedule.nextFilingDeadline} (${t} day(s)); initial audit due ${s.schedule.initialAuditDueDate}.`:"CAR does not apply (not a DCPMI)."});}let p=((u=e.breaches)!=null?u:[]).map(t=>({id:t.id,title:t.title,assessment:chunkY346CURW_js.a(t,c.breachOptions)}));for(let t of p){let o=t.assessment,C=o.timing.overdue?"fail":o.complete?"pass":"warn",A=Number.isFinite(o.timing.deadline)?o.timing.overdue?`${Math.abs(o.timing.hoursRemaining)}h overdue`:`${Math.max(0,o.timing.hoursRemaining)}h remaining`:"discovery date not set";a.push({id:`breach:${t.id}`,label:`Breach notification \u2014 ${t.title} (NDPA S. 40)`,status:C,detail:`${o.completeness}% complete; ${A}.`});}let l={pass:a.filter(t=>t.status==="pass").length,warn:a.filter(t=>t.status==="warn").length,fail:a.filter(t=>t.status==="fail").length};return {passed:i.score>=r&&l.fail===0,score:i.score,rating:i.rating,minScore:r,checks:a,compliance:i,dcpmi:n,car:s,breaches:p,summary:l,generatedAt:new Date().toISOString().slice(0,10)}}var $={pass:"\u2713",warn:"!",fail:"\u2717"},R={pass:"\x1B[32m",warn:"\x1B[33m",fail:"\x1B[31m"},y="\x1B[0m";function w(e,c={}){let r=(a,n)=>c.color?`${R[a]}${n}${y}`:n,i=[];i.push("NDPA 2023 Compliance Audit"),i.push(`Generated ${e.generatedAt}`),i.push(""),i.push(`Compliance score: ${e.score}/100 (${e.rating}) \u2014 minimum ${e.minScore}`),i.push("");for(let a of e.checks)i.push(`${r(a.status,$[a.status])} ${a.label}`),i.push(` ${a.detail}`);return i.push(""),i.push(`${e.summary.pass} passed, ${e.summary.warn} warning(s), ${e.summary.fail} failed`),i.push(r(e.passed?"pass":"fail",`Verdict: ${e.passed?"PASS":"FAIL"}`)),i.join(`
|
|
2
2
|
`)}exports.a=P;exports.b=w;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {c,d as d$1}from'./chunk-MGXWQW5I.mjs';import {a as a$1}from'./chunk-6A7M4CGJ.mjs';import {a}from'./chunk-WJSUVPYX.mjs';import {d}from'./chunk-675DXBED.mjs';import {useMemo,useState,useRef,useCallback,useEffect}from'react';function h(e,o){return useMemo(()=>a(e,o),[e,o])}function x({input:e}){let o=JSON.stringify(e);return useMemo(()=>a$1(e),[o])}function b(e,o){return useMemo(()=>c(e,o),[e.dataSubjectsInSixMonths,e.isDesignated,o])}function v(e,o){let[u,f]=useState(null),i=useRef(e),r=useRef(o);i.current=e,r.current=o;let t=useCallback(()=>{f(d(i.current,r.current));},[]);return useEffect(()=>{t();},[t]),{result:u,rescan:t}}function q(e,o){return useMemo(()=>d$1(e,o),[e.commencementDate,e.asOf,e.tier,o])}export{h as a,x as b,b as c,v as d,q as e};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {c,d}from'./chunk-
|
|
1
|
+
import {c,d}from'./chunk-MGXWQW5I.mjs';import {a}from'./chunk-6A7M4CGJ.mjs';import {a as a$1}from'./chunk-WJSUVPYX.mjs';var b=e=>`\u20A6${e.toLocaleString("en-NG")}`;function P(e,c$1={}){var m,u;let r=(m=c$1.minScore)!=null?m:70,i=a(e.compliance),a$2=[];a$2.push({id:"compliance-score",label:"Overall compliance score",status:i.score>=r?"pass":"fail",detail:`${i.score}/100 (${i.rating}); minimum ${r}.`});for(let t of i.recommendations)t.priority!=="critical"&&t.priority!=="high"||a$2.push({id:`gap:${t.module}:${t.key}`,label:`${t.label} (${t.ndpaSection})`,status:t.priority==="critical"?"fail":"warn",detail:t.recommendation});let n;e.dcpmi&&(n=c(e.dcpmi,c$1.dcpmiOptions),a$2.push({id:"dcpmi",label:"DCPMI registration (GAID 2025)",status:n.tier==="listed"?"warn":"pass",detail:n.isDCPMI?`${n.tier} \u2014 ${b(n.annualFeeNGN)}/yr; ${n.registration.renewsAnnually?"renew registration annually":"register once + file CAR annually"}.`:"Not a Data Controller/Processor of Major Importance by volume."}));let s;if(e.car){s=d(e.car,c$1.carOptions);let t=s.status.daysUntilNextDeadline;a$2.push({id:"car",label:"Compliance Audit Returns (NDPC GAID 2025)",status:s.applicable&&(s.status.initialAuditDue||t<=30)?"warn":"pass",detail:s.applicable?`Next filing ${s.schedule.nextFilingDeadline} (${t} day(s)); initial audit due ${s.schedule.initialAuditDueDate}.`:"CAR does not apply (not a DCPMI)."});}let p=((u=e.breaches)!=null?u:[]).map(t=>({id:t.id,title:t.title,assessment:a$1(t,c$1.breachOptions)}));for(let t of p){let o=t.assessment,C=o.timing.overdue?"fail":o.complete?"pass":"warn",A=Number.isFinite(o.timing.deadline)?o.timing.overdue?`${Math.abs(o.timing.hoursRemaining)}h overdue`:`${Math.max(0,o.timing.hoursRemaining)}h remaining`:"discovery date not set";a$2.push({id:`breach:${t.id}`,label:`Breach notification \u2014 ${t.title} (NDPA S. 40)`,status:C,detail:`${o.completeness}% complete; ${A}.`});}let l={pass:a$2.filter(t=>t.status==="pass").length,warn:a$2.filter(t=>t.status==="warn").length,fail:a$2.filter(t=>t.status==="fail").length};return {passed:i.score>=r&&l.fail===0,score:i.score,rating:i.rating,minScore:r,checks:a$2,compliance:i,dcpmi:n,car:s,breaches:p,summary:l,generatedAt:new Date().toISOString().slice(0,10)}}var $={pass:"\u2713",warn:"!",fail:"\u2717"},R={pass:"\x1B[32m",warn:"\x1B[33m",fail:"\x1B[31m"},y="\x1B[0m";function w(e,c={}){let r=(a,n)=>c.color?`${R[a]}${n}${y}`:n,i=[];i.push("NDPA 2023 Compliance Audit"),i.push(`Generated ${e.generatedAt}`),i.push(""),i.push(`Compliance score: ${e.score}/100 (${e.rating}) \u2014 minimum ${e.minScore}`),i.push("");for(let a of e.checks)i.push(`${r(a.status,$[a.status])} ${a.label}`),i.push(` ${a.detail}`);return i.push(""),i.push(`${e.summary.pass} passed, ${e.summary.warn} warning(s), ${e.summary.fail} failed`),i.push(r(e.passed?"pass":"fail",`Verdict: ${e.passed?"PASS":"FAIL"}`)),i.join(`
|
|
2
2
|
`)}export{P as a,w as b};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {a}from'./chunk-ZJYULEER.mjs';var y={ohl:200,ehl:1e3,uhl:5e3},N={UHL:25e4,EHL:1e5,OHL:1e4};function S(e,i={}){let t=a(a({},y),i.thresholds),r=a(a({},N),i.fees),a$1=e==null?void 0:e.dataSubjectsInSixMonths,l=typeof a$1=="number"&&a$1>0?Math.floor(a$1):0,n;l>t.uhl?n="UHL":l>=t.ehl?n="EHL":l>=t.ohl?n="OHL":e!=null&&e.isDesignated?n="listed":n="none";let u=n!=="none",c=n==="UHL"||n==="EHL"||n==="OHL"?r[n]:0,s=[];return n==="listed"&&s.push("Designated as a DCPMI below the volume tiers \u2014 confirm the applicable registration tier and fee with the NDPC."),u&&s.push(n==="OHL"?"OHL organisations renew their NDPC registration annually and are not required to file Compliance Audit Returns (CAR).":n==="listed"?"Confirm with the NDPC whether your designation falls under UHL/EHL (register once, file CAR annually) or OHL (renew registration annually).":"Register once with the NDPC, then file Compliance Audit Returns (CAR) annually."),s.push("Thresholds, fees, and filing dates follow the NDPC GAID 2025 baseline and can change \u2014 verify against current NDPC guidance before relying on them."),{tier:n,isDCPMI:u,annualFeeNGN:c,registration:{required:u,renewsAnnually:n==="OHL"},compliance:{auditReturnsAnnual:n==="UHL"||n==="EHL",initialAuditWithinMonths:15},notes:s,dataSubjectsConsidered:l}}function L(e){return String(e).padStart(2,"0")}function H(e){let[i,t,r]=e.split("-").map(Number);return new Date(Date.UTC(i,t-1,r))}function w(e){return e.toISOString().slice(0,10)}function R(e,i){let[t,r,a]=e.split("-").map(Number);return w(new Date(Date.UTC(t,r-1+i,a)))}function x(){return new Date().toISOString().slice(0,10)}function E(e,i={}){var C,f,g,b,p,M,P;let t=(C=e.asOf)!=null?C:x(),r=(f=i.initialAuditWithinMonths)!=null?f:15,a=(b=(g=i.annualDeadline)==null?void 0:g.month)!=null?b:3,l=(M=(p=i.annualDeadline)==null?void 0:p.day)!=null?M:31,n=(P=i.deadlineOverrides)!=null?P:{},u=e.tier===void 0?true:e.tier==="UHL"||e.tier==="EHL",c=R(e.commencementDate,r),s=I=>{var A;return (A=n[I])!=null?A:`${I}-${L(a)}-${L(l)}`},h=Number(t.slice(0,4)),D=s(h);t>D&&(h+=1,D=s(h));let O=Math.round((H(D).getTime()-H(t).getTime())/864e5),m=t>=c,o=[];return u?(o.push("File the Compliance Audit Return with the NDPC via the NDPC Information Management Portal (NIMP)."),m&&o.push("The initial compliance-audit window has elapsed \u2014 ensure the initial audit has been conducted.")):e.tier==="OHL"?o.push("OHL organisations renew their NDPC registration annually and are not required to file Compliance Audit Returns (CAR)."):e.tier==="listed"?o.push("Confirm with the NDPC whether your designation requires filing CAR (UHL/EHL) or annual registration renewal (OHL)."):o.push("Compliance Audit Returns apply to Data Controllers/Processors of Major Importance in the UHL and EHL categories."),o.push("Filing deadlines follow the NDPC GAID 2025 baseline and can be extended \u2014 verify the current deadline with the NDPC."),{applicable:u,schedule:{commencementDate:e.commencementDate,initialAuditWithinMonths:r,initialAuditDueDate:c,nextFilingDeadline:D,filingYear:h},status:{initialAuditDue:m,daysUntilNextDeadline:O},notes:o,asOf:t}}export{y as a,N as b,S as c,E as d};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js');var y={ohl:200,ehl:1e3,uhl:5e3},N={UHL:25e4,EHL:1e5,OHL:1e4};function S(e,i={}){let t=chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},y),i.thresholds),r=chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},N),i.fees),a=e==null?void 0:e.dataSubjectsInSixMonths,l=typeof a=="number"&&a>0?Math.floor(a):0,n;l>t.uhl?n="UHL":l>=t.ehl?n="EHL":l>=t.ohl?n="OHL":e!=null&&e.isDesignated?n="listed":n="none";let u=n!=="none",c=n==="UHL"||n==="EHL"||n==="OHL"?r[n]:0,s=[];return n==="listed"&&s.push("Designated as a DCPMI below the volume tiers \u2014 confirm the applicable registration tier and fee with the NDPC."),u&&s.push(n==="OHL"?"OHL organisations renew their NDPC registration annually and are not required to file Compliance Audit Returns (CAR).":n==="listed"?"Confirm with the NDPC whether your designation falls under UHL/EHL (register once, file CAR annually) or OHL (renew registration annually).":"Register once with the NDPC, then file Compliance Audit Returns (CAR) annually."),s.push("Thresholds, fees, and filing dates follow the NDPC GAID 2025 baseline and can change \u2014 verify against current NDPC guidance before relying on them."),{tier:n,isDCPMI:u,annualFeeNGN:c,registration:{required:u,renewsAnnually:n==="OHL"},compliance:{auditReturnsAnnual:n==="UHL"||n==="EHL",initialAuditWithinMonths:15},notes:s,dataSubjectsConsidered:l}}function L(e){return String(e).padStart(2,"0")}function H(e){let[i,t,r]=e.split("-").map(Number);return new Date(Date.UTC(i,t-1,r))}function w(e){return e.toISOString().slice(0,10)}function R(e,i){let[t,r,a]=e.split("-").map(Number);return w(new Date(Date.UTC(t,r-1+i,a)))}function x(){return new Date().toISOString().slice(0,10)}function E(e,i={}){var C,f,g,b,p,M,P;let t=(C=e.asOf)!=null?C:x(),r=(f=i.initialAuditWithinMonths)!=null?f:15,a=(b=(g=i.annualDeadline)==null?void 0:g.month)!=null?b:3,l=(M=(p=i.annualDeadline)==null?void 0:p.day)!=null?M:31,n=(P=i.deadlineOverrides)!=null?P:{},u=e.tier===void 0?true:e.tier==="UHL"||e.tier==="EHL",c=R(e.commencementDate,r),s=I=>{var A;return (A=n[I])!=null?A:`${I}-${L(a)}-${L(l)}`},h=Number(t.slice(0,4)),D=s(h);t>D&&(h+=1,D=s(h));let O=Math.round((H(D).getTime()-H(t).getTime())/864e5),m=t>=c,o=[];return u?(o.push("File the Compliance Audit Return with the NDPC via the NDPC Information Management Portal (NIMP)."),m&&o.push("The initial compliance-audit window has elapsed \u2014 ensure the initial audit has been conducted.")):e.tier==="OHL"?o.push("OHL organisations renew their NDPC registration annually and are not required to file Compliance Audit Returns (CAR)."):e.tier==="listed"?o.push("Confirm with the NDPC whether your designation requires filing CAR (UHL/EHL) or annual registration renewal (OHL)."):o.push("Compliance Audit Returns apply to Data Controllers/Processors of Major Importance in the UHL and EHL categories."),o.push("Filing deadlines follow the NDPC GAID 2025 baseline and can be extended \u2014 verify the current deadline with the NDPC."),{applicable:u,schedule:{commencementDate:e.commencementDate,initialAuditWithinMonths:r,initialAuditDueDate:c,nextFilingDeadline:D,filingYear:h},status:{initialAuditDue:m,daysUntilNextDeadline:O},notes:o,asOf:t}}exports.a=y;exports.b=N;exports.c=S;exports.d=E;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import {a as a$2,b}from'./chunk-XC3DLYEG.mjs';import {a}from'./chunk-
|
|
1
|
+
import {a as a$2,b}from'./chunk-XC3DLYEG.mjs';import {a}from'./chunk-675DXBED.mjs';import {a as a$1}from'./chunk-DBZSN4WP.mjs';import {useRef,useState,useEffect,useCallback}from'react';function F(o){if(!o)return a$1("ndpr_consent");let{storageKey:n="ndpr_consent",storageType:i="localStorage"}=o;return i==="sessionStorage"?a$2(n):i==="cookie"?b(n,o.cookieOptions):a$1(n)}function V(o,n,i,r,a$1,p,l){if(o){i(o);let{valid:s,errors:c}=a(o);r(s),a$1(c),p(!(s&&o.version===n));}else p(true);l(false);}function z({options:o,adapter:n,storageOptions:i,version:r="1.0",onChange:a$1}){let p=n!=null?n:F(i),l=useRef(p);l.current=p;let[s,c]=useState(null),[y,d]=useState(false),[O,S]=useState(false),[k,C]=useState([]),[w,v]=useState(true);useEffect(()=>{let t=false;try{let e=l.current.load();e instanceof Promise?e.then(m=>{t||V(m,r,c,S,C,d,v);},()=>{t||(d(!0),v(!1));}):V(e,r,c,S,C,d,v);}catch(e){t||(d(true),v(false));}return ()=>{t=true;}},[r]);let h=useCallback(t=>{let{valid:e,errors:m}=a(t);S(e),C(m),a$1==null||a$1(t),Promise.resolve(l.current.save(t)).catch(j=>{console.warn("[ndpr-toolkit] Failed to save consent:",j);});},[a$1]),f=useCallback(t=>{let e={consents:t,timestamp:Date.now(),version:r,method:"explicit",hasInteracted:true};c(e),h(e),d(false);},[r,h]),x=useCallback(()=>{let t={};o.forEach(e=>{t[e.id]=true;}),f(t);},[o,f]),I=useCallback(()=>{let t={};o.forEach(e=>{t[e.id]=e.required||false;}),f(t);},[o,f]),L=useCallback(t=>!!(s!=null&&s.consents[t]),[s]),U=useCallback(()=>{c(null),d(true),S(false),C([]),Promise.resolve(l.current.remove()).catch(t=>{console.warn("[ndpr-toolkit] Failed to remove consent:",t);});},[]);return {settings:s,hasConsent:L,updateConsent:f,acceptAll:x,rejectAll:I,shouldShowBanner:y,isValid:O,validationErrors:k,resetConsent:U,isLoading:w}}export{z as a};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';function S(r){let e=[];if((!r.consents||Object.keys(r.consents).length===0)&&e.push({field:"consents",code:"consents_required",message:"Consent settings must include at least one consent option"}),r.timestamp?(typeof r.timestamp!="number"||isNaN(r.timestamp))&&e.push({field:"timestamp",code:"timestamp_invalid",message:"Consent timestamp must be a valid number"}):e.push({field:"timestamp",code:"timestamp_required",message:"Consent timestamp is required"}),r.version||e.push({field:"version",code:"version_required",message:"Consent version is required"}),r.method||e.push({field:"method",code:"method_required",message:"Consent collection method is required"}),r.hasInteracted===void 0&&e.push({field:"hasInteracted",code:"has_interacted_required",message:"User interaction status is required"}),r.timestamp){let o=new Date;o.setMonth(o.getMonth()-13);let n=o.getTime();r.timestamp<n&&e.push({field:"timestamp",code:"consent_stale",message:"Consent is older than 13 months and should be refreshed"});}return e.length>0?{valid:false,errors:e}:{valid:true,errors:[],data:r}}function b(r){let e=[];return (!r||r.length===0)&&e.push({field:"options",code:"options_required",message:"At least one consent option is required"}),r==null||r.forEach((o,n)=>{(!o.purpose||o.purpose.trim()==="")&&e.push({field:`options[${n}].purpose`,code:"purpose_required",message:`Consent option "${o.id}" is missing a purpose. NDPA Section 26 requires consent to be specific to a stated purpose.`});}),e.length>0?{valid:false,errors:e}:{valid:true,errors:[],data:r}}var v=[{name:"_ga",category:"analytics",provider:"Google Analytics",purpose:"Distinguishes users"},{name:"_ga_",prefix:true,category:"analytics",provider:"Google Analytics (GA4)",purpose:"Persists session state"},{name:"_gid",category:"analytics",provider:"Google Analytics",purpose:"Distinguishes users"},{name:"_gat",prefix:true,category:"analytics",provider:"Google Analytics",purpose:"Throttles request rate"},{name:"_dc_gtm_",prefix:true,category:"analytics",provider:"Google Tag Manager",purpose:"Throttles request rate"},{name:"_gcl_",prefix:true,category:"marketing",provider:"Google Ads",purpose:"Conversion tracking"},{name:"IDE",category:"marketing",provider:"Google DoubleClick",purpose:"Ad targeting"},{name:"test_cookie",category:"marketing",provider:"Google DoubleClick",purpose:"Checks cookie support"},{name:"_fbp",category:"marketing",provider:"Meta (Facebook)",purpose:"Ad delivery and measurement"},{name:"_fbc",category:"marketing",provider:"Meta (Facebook)",purpose:"Click attribution"},{name:"fr",category:"marketing",provider:"Meta (Facebook)",purpose:"Ad delivery and measurement"},{name:"_clck",category:"analytics",provider:"Microsoft Clarity",purpose:"Session analytics"},{name:"_clsk",category:"analytics",provider:"Microsoft Clarity",purpose:"Session analytics"},{name:"_hj",prefix:true,category:"analytics",provider:"Hotjar",purpose:"Behaviour analytics"},{name:"bcookie",category:"marketing",provider:"LinkedIn",purpose:"Browser identification"},{name:"lidc",category:"marketing",provider:"LinkedIn",purpose:"Routing / ad delivery"},{name:"li_",prefix:true,category:"marketing",provider:"LinkedIn",purpose:"Ad delivery"},{name:"_ttp",category:"marketing",provider:"TikTok",purpose:"Ad measurement"},{name:"personalization_id",category:"marketing",provider:"X (Twitter)",purpose:"Ad personalisation"},{name:"guest_id",category:"marketing",provider:"X (Twitter)",purpose:"Identifies the browser"},{name:"hubspotutk",category:"marketing",provider:"HubSpot",purpose:"Visitor identification"},{name:"__hs",prefix:true,category:"analytics",provider:"HubSpot",purpose:"Analytics / session"},{name:"__stripe_mid",category:"necessary",provider:"Stripe",purpose:"Fraud prevention"},{name:"__stripe_sid",category:"necessary",provider:"Stripe",purpose:"Fraud prevention"},{name:"intercom-",prefix:true,category:"functional",provider:"Intercom",purpose:"Live chat / messaging"},{name:"ndpr_consent",category:"necessary",provider:"NDPR Toolkit",purpose:"Stores the consent decision"}];function k(r,e){return e.name instanceof RegExp?e.name.test(r):e.prefix?r.startsWith(e.name):r===e.name}function C(r){return r.split(";").map(e=>{let o=e.trim(),n=o.indexOf("=");return (n===-1?o:o.slice(0,n)).trim()}).filter(e=>e.length>0)}function A(r=[],e={}){var u,l,m,g,f,y;let o=(u=e.cookieString)!=null?u:typeof document!="undefined"?document.cookie:"",n=(l=e.asOf)!=null?l:Date.now(),h=((m=e.useKnownRegistry)!=null?m:true)?[...(g=e.knownCookies)!=null?g:[],...v]:[],a=C(o).map(t=>{let i=r.find(d=>k(t,d));if(i)return {name:t,category:i.category,matchedBy:"declared",provider:i.provider,purpose:i.purpose};let c=h.find(d=>k(t,d));return c?{name:t,category:c.category,matchedBy:"known",provider:c.provider,purpose:c.purpose}:{name:t,category:null,matchedBy:"none"}}),s={};for(let t of a){let i=(f=t.category)!=null?f:"uncategorized";((y=s[i])!=null?y:s[i]=[]).push(t);}let p=a.filter(t=>t.matchedBy!=="declared");return {scannedAt:n,total:a.length,cookies:a,declared:a.filter(t=>t.matchedBy==="declared"),undeclared:p,identified:a.filter(t=>t.matchedBy==="known"),unknown:a.filter(t=>t.matchedBy==="none"),byCategory:s,complete:p.length===0}}exports.a=S;exports.b=b;exports.c=v;exports.d=A;
|
package/dist/consent.d.mts
CHANGED
|
@@ -487,6 +487,44 @@ declare interface ConsentStorageProps {
|
|
|
487
487
|
}) => React__default.ReactNode);
|
|
488
488
|
}
|
|
489
489
|
|
|
490
|
+
/** How a present cookie was classified. */
|
|
491
|
+
export declare type CookieMatchSource = 'declared' | 'known' | 'none';
|
|
492
|
+
|
|
493
|
+
export declare interface CookieScanOptions {
|
|
494
|
+
/**
|
|
495
|
+
* The cookie string to scan, in `document.cookie` form (`a=1; b=2`).
|
|
496
|
+
* Defaults to `document.cookie` in the browser, or `''` on the server.
|
|
497
|
+
*/
|
|
498
|
+
cookieString?: string;
|
|
499
|
+
/** Reference timestamp (epoch ms) recorded on the result. Defaults to `Date.now()`. */
|
|
500
|
+
asOf?: number;
|
|
501
|
+
/** Extra known cookies, checked before the built-in registry (so they can override it). */
|
|
502
|
+
knownCookies?: DeclaredCookie[];
|
|
503
|
+
/** Whether to fall back to the built-in known-cookie registry for undeclared cookies. @default true */
|
|
504
|
+
useKnownRegistry?: boolean;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export declare interface CookieScanResult {
|
|
508
|
+
/** When the scan ran (epoch ms). */
|
|
509
|
+
scannedAt: number;
|
|
510
|
+
/** Number of cookies present. */
|
|
511
|
+
total: number;
|
|
512
|
+
/** Every present cookie, classified. */
|
|
513
|
+
cookies: ScannedCookie[];
|
|
514
|
+
/** Cookies that matched one of your declared cookies. */
|
|
515
|
+
declared: ScannedCookie[];
|
|
516
|
+
/** Cookies present but NOT in your declaration — the compliance gap. */
|
|
517
|
+
undeclared: ScannedCookie[];
|
|
518
|
+
/** Undeclared cookies the built-in registry could still identify. */
|
|
519
|
+
identified: ScannedCookie[];
|
|
520
|
+
/** Undeclared cookies that could not be identified at all. */
|
|
521
|
+
unknown: ScannedCookie[];
|
|
522
|
+
/** Present cookies grouped by resolved category; unclassified cookies go under `uncategorized`. */
|
|
523
|
+
byCategory: Record<string, ScannedCookie[]>;
|
|
524
|
+
/** True when there are no undeclared cookies. */
|
|
525
|
+
complete: boolean;
|
|
526
|
+
}
|
|
527
|
+
|
|
490
528
|
/**
|
|
491
529
|
* Creates a new audit entry from consent settings. If `previousSettings` is
|
|
492
530
|
* provided, the action is automatically determined by comparing old and new
|
|
@@ -494,6 +532,30 @@ declare interface ConsentStorageProps {
|
|
|
494
532
|
*/
|
|
495
533
|
export declare function createAuditEntry(settings: ConsentSettings, previousSettings?: ConsentSettings | null, actionOverride?: ConsentAuditEntry['action']): ConsentAuditEntry;
|
|
496
534
|
|
|
535
|
+
/**
|
|
536
|
+
* Cookie scanner — audits the cookies actually present in the browser against
|
|
537
|
+
* the cookies you have declared, surfacing undeclared cookies that put you out
|
|
538
|
+
* of step with your cookie notice (NDPA 2023 S.25-26 / NDPC GAID 2025 on
|
|
539
|
+
* specific, informed consent).
|
|
540
|
+
*
|
|
541
|
+
* Pure and DOM-optional: pass `cookieString` to scan an arbitrary value (a
|
|
542
|
+
* `Cookie:` header on the server, a test fixture), or call it in the browser
|
|
543
|
+
* and it reads `document.cookie`. Safe to import from a server bundle.
|
|
544
|
+
*/
|
|
545
|
+
/** A cookie you declare against a consent category. */
|
|
546
|
+
export declare interface DeclaredCookie {
|
|
547
|
+
/** Exact cookie name, a prefix (with `prefix: true`), or a RegExp matched against the name. */
|
|
548
|
+
name: string | RegExp;
|
|
549
|
+
/** Consent category this cookie belongs to (e.g. 'necessary', 'analytics', 'marketing'). */
|
|
550
|
+
category: string;
|
|
551
|
+
/** Who sets the cookie (e.g. 'Google Analytics'). */
|
|
552
|
+
provider?: string;
|
|
553
|
+
/** What the cookie is used for — surfaced in your cookie policy. */
|
|
554
|
+
purpose?: string;
|
|
555
|
+
/** Treat a string `name` as a prefix match instead of an exact match. Ignored for RegExp names. */
|
|
556
|
+
prefix?: boolean;
|
|
557
|
+
}
|
|
558
|
+
|
|
497
559
|
/**
|
|
498
560
|
* Retrieves the full consent audit log from localStorage.
|
|
499
561
|
* Returns an empty array if no log exists or parsing fails.
|
|
@@ -502,6 +564,14 @@ export declare function createAuditEntry(settings: ConsentSettings, previousSett
|
|
|
502
564
|
*/
|
|
503
565
|
export declare function getAuditLog(storageKey?: string): ConsentAuditEntry[];
|
|
504
566
|
|
|
567
|
+
/**
|
|
568
|
+
* Built-in registry of widely deployed third-party cookies, so an undeclared
|
|
569
|
+
* cookie can often still be identified (provider + likely category). Override
|
|
570
|
+
* or extend via {@link CookieScanOptions.knownCookies}; categories follow the
|
|
571
|
+
* common necessary / functional / analytics / marketing taxonomy.
|
|
572
|
+
*/
|
|
573
|
+
export declare const KNOWN_COOKIES: DeclaredCookie[];
|
|
574
|
+
|
|
505
575
|
/**
|
|
506
576
|
* Lawful basis for processing personal data per NDPA Section 25(1)
|
|
507
577
|
*/
|
|
@@ -539,6 +609,24 @@ declare interface SaveButtonProps {
|
|
|
539
609
|
consents?: Record<string, boolean>;
|
|
540
610
|
}
|
|
541
611
|
|
|
612
|
+
/**
|
|
613
|
+
* Scan the cookies present against your declared cookies and a registry of
|
|
614
|
+
* well-known third-party cookies. Returns which cookies are declared, which are
|
|
615
|
+
* undeclared (and whether they can still be identified), and a per-category view.
|
|
616
|
+
*/
|
|
617
|
+
export declare function scanCookies(declared?: DeclaredCookie[], options?: CookieScanOptions): CookieScanResult;
|
|
618
|
+
|
|
619
|
+
export declare interface ScannedCookie {
|
|
620
|
+
/** The cookie name as found in the cookie string. */
|
|
621
|
+
name: string;
|
|
622
|
+
/** Resolved consent category, or `null` when it could not be classified. */
|
|
623
|
+
category: string | null;
|
|
624
|
+
/** Whether it matched your declaration, only the known registry, or nothing. */
|
|
625
|
+
matchedBy: CookieMatchSource;
|
|
626
|
+
provider?: string;
|
|
627
|
+
purpose?: string;
|
|
628
|
+
}
|
|
629
|
+
|
|
542
630
|
export declare interface StorageAdapter<T = unknown> {
|
|
543
631
|
/** Load persisted data. Called once on hook mount. */
|
|
544
632
|
load(): T | null | Promise<T | null>;
|
package/dist/consent.d.ts
CHANGED
|
@@ -487,6 +487,44 @@ declare interface ConsentStorageProps {
|
|
|
487
487
|
}) => React__default.ReactNode);
|
|
488
488
|
}
|
|
489
489
|
|
|
490
|
+
/** How a present cookie was classified. */
|
|
491
|
+
export declare type CookieMatchSource = 'declared' | 'known' | 'none';
|
|
492
|
+
|
|
493
|
+
export declare interface CookieScanOptions {
|
|
494
|
+
/**
|
|
495
|
+
* The cookie string to scan, in `document.cookie` form (`a=1; b=2`).
|
|
496
|
+
* Defaults to `document.cookie` in the browser, or `''` on the server.
|
|
497
|
+
*/
|
|
498
|
+
cookieString?: string;
|
|
499
|
+
/** Reference timestamp (epoch ms) recorded on the result. Defaults to `Date.now()`. */
|
|
500
|
+
asOf?: number;
|
|
501
|
+
/** Extra known cookies, checked before the built-in registry (so they can override it). */
|
|
502
|
+
knownCookies?: DeclaredCookie[];
|
|
503
|
+
/** Whether to fall back to the built-in known-cookie registry for undeclared cookies. @default true */
|
|
504
|
+
useKnownRegistry?: boolean;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export declare interface CookieScanResult {
|
|
508
|
+
/** When the scan ran (epoch ms). */
|
|
509
|
+
scannedAt: number;
|
|
510
|
+
/** Number of cookies present. */
|
|
511
|
+
total: number;
|
|
512
|
+
/** Every present cookie, classified. */
|
|
513
|
+
cookies: ScannedCookie[];
|
|
514
|
+
/** Cookies that matched one of your declared cookies. */
|
|
515
|
+
declared: ScannedCookie[];
|
|
516
|
+
/** Cookies present but NOT in your declaration — the compliance gap. */
|
|
517
|
+
undeclared: ScannedCookie[];
|
|
518
|
+
/** Undeclared cookies the built-in registry could still identify. */
|
|
519
|
+
identified: ScannedCookie[];
|
|
520
|
+
/** Undeclared cookies that could not be identified at all. */
|
|
521
|
+
unknown: ScannedCookie[];
|
|
522
|
+
/** Present cookies grouped by resolved category; unclassified cookies go under `uncategorized`. */
|
|
523
|
+
byCategory: Record<string, ScannedCookie[]>;
|
|
524
|
+
/** True when there are no undeclared cookies. */
|
|
525
|
+
complete: boolean;
|
|
526
|
+
}
|
|
527
|
+
|
|
490
528
|
/**
|
|
491
529
|
* Creates a new audit entry from consent settings. If `previousSettings` is
|
|
492
530
|
* provided, the action is automatically determined by comparing old and new
|
|
@@ -494,6 +532,30 @@ declare interface ConsentStorageProps {
|
|
|
494
532
|
*/
|
|
495
533
|
export declare function createAuditEntry(settings: ConsentSettings, previousSettings?: ConsentSettings | null, actionOverride?: ConsentAuditEntry['action']): ConsentAuditEntry;
|
|
496
534
|
|
|
535
|
+
/**
|
|
536
|
+
* Cookie scanner — audits the cookies actually present in the browser against
|
|
537
|
+
* the cookies you have declared, surfacing undeclared cookies that put you out
|
|
538
|
+
* of step with your cookie notice (NDPA 2023 S.25-26 / NDPC GAID 2025 on
|
|
539
|
+
* specific, informed consent).
|
|
540
|
+
*
|
|
541
|
+
* Pure and DOM-optional: pass `cookieString` to scan an arbitrary value (a
|
|
542
|
+
* `Cookie:` header on the server, a test fixture), or call it in the browser
|
|
543
|
+
* and it reads `document.cookie`. Safe to import from a server bundle.
|
|
544
|
+
*/
|
|
545
|
+
/** A cookie you declare against a consent category. */
|
|
546
|
+
export declare interface DeclaredCookie {
|
|
547
|
+
/** Exact cookie name, a prefix (with `prefix: true`), or a RegExp matched against the name. */
|
|
548
|
+
name: string | RegExp;
|
|
549
|
+
/** Consent category this cookie belongs to (e.g. 'necessary', 'analytics', 'marketing'). */
|
|
550
|
+
category: string;
|
|
551
|
+
/** Who sets the cookie (e.g. 'Google Analytics'). */
|
|
552
|
+
provider?: string;
|
|
553
|
+
/** What the cookie is used for — surfaced in your cookie policy. */
|
|
554
|
+
purpose?: string;
|
|
555
|
+
/** Treat a string `name` as a prefix match instead of an exact match. Ignored for RegExp names. */
|
|
556
|
+
prefix?: boolean;
|
|
557
|
+
}
|
|
558
|
+
|
|
497
559
|
/**
|
|
498
560
|
* Retrieves the full consent audit log from localStorage.
|
|
499
561
|
* Returns an empty array if no log exists or parsing fails.
|
|
@@ -502,6 +564,14 @@ export declare function createAuditEntry(settings: ConsentSettings, previousSett
|
|
|
502
564
|
*/
|
|
503
565
|
export declare function getAuditLog(storageKey?: string): ConsentAuditEntry[];
|
|
504
566
|
|
|
567
|
+
/**
|
|
568
|
+
* Built-in registry of widely deployed third-party cookies, so an undeclared
|
|
569
|
+
* cookie can often still be identified (provider + likely category). Override
|
|
570
|
+
* or extend via {@link CookieScanOptions.knownCookies}; categories follow the
|
|
571
|
+
* common necessary / functional / analytics / marketing taxonomy.
|
|
572
|
+
*/
|
|
573
|
+
export declare const KNOWN_COOKIES: DeclaredCookie[];
|
|
574
|
+
|
|
505
575
|
/**
|
|
506
576
|
* Lawful basis for processing personal data per NDPA Section 25(1)
|
|
507
577
|
*/
|
|
@@ -539,6 +609,24 @@ declare interface SaveButtonProps {
|
|
|
539
609
|
consents?: Record<string, boolean>;
|
|
540
610
|
}
|
|
541
611
|
|
|
612
|
+
/**
|
|
613
|
+
* Scan the cookies present against your declared cookies and a registry of
|
|
614
|
+
* well-known third-party cookies. Returns which cookies are declared, which are
|
|
615
|
+
* undeclared (and whether they can still be identified), and a per-category view.
|
|
616
|
+
*/
|
|
617
|
+
export declare function scanCookies(declared?: DeclaredCookie[], options?: CookieScanOptions): CookieScanResult;
|
|
618
|
+
|
|
619
|
+
export declare interface ScannedCookie {
|
|
620
|
+
/** The cookie name as found in the cookie string. */
|
|
621
|
+
name: string;
|
|
622
|
+
/** Resolved consent category, or `null` when it could not be classified. */
|
|
623
|
+
category: string | null;
|
|
624
|
+
/** Whether it matched your declaration, only the known registry, or nothing. */
|
|
625
|
+
matchedBy: CookieMatchSource;
|
|
626
|
+
provider?: string;
|
|
627
|
+
purpose?: string;
|
|
628
|
+
}
|
|
629
|
+
|
|
542
630
|
export declare interface StorageAdapter<T = unknown> {
|
|
543
631
|
/** Load persisted data. Called once on hook mount. */
|
|
544
632
|
load(): T | null | Promise<T | null>;
|
package/dist/consent.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
'use strict';var chunkSJDDNB6M_js=require('./chunk-SJDDNB6M.js'),chunkC32TMS75_js=require('./chunk-C32TMS75.js'),chunkPXUX4FYM_js=require('./chunk-PXUX4FYM.js'),chunk3IA3KDII_js=require('./chunk-3IA3KDII.js'),
|
|
2
|
+
'use strict';var chunkSJDDNB6M_js=require('./chunk-SJDDNB6M.js'),chunkC32TMS75_js=require('./chunk-C32TMS75.js'),chunkPXUX4FYM_js=require('./chunk-PXUX4FYM.js'),chunk3IA3KDII_js=require('./chunk-3IA3KDII.js'),chunkGJH7YFBO_js=require('./chunk-GJH7YFBO.js');require('./chunk-L2VO3MEJ.js'),require('./chunk-C2KEXHRX.js');var chunkZVWSSXV2_js=require('./chunk-ZVWSSXV2.js'),chunkAME4HJR4_js=require('./chunk-AME4HJR4.js');require('./chunk-I5ZDNSX5.js'),require('./chunk-7563FVMY.js'),require('./chunk-VWED6UTN.js');var chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),react=require('react'),jsxRuntime=require('react/jsx-runtime');var v=react.createContext(null);function p(){let t=react.useContext(v);if(!t)throw new Error("Consent compound components must be wrapped in <Consent.Provider>. Example: <Consent.Provider options={...}><Consent.Banner /></Consent.Provider>");return t}var g=({options:t,adapter:n,version:s,onChange:r,children:c})=>{let d=chunkGJH7YFBO_js.a({options:t,adapter:n,version:s,onChange:r}),o=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},d),{options:t});return jsxRuntime.jsx(v.Provider,{value:o,children:c})};var B=({classNames:t,unstyled:n})=>{let{options:s,settings:r}=p(),[c,d]=react.useState(()=>{let o={};return s.forEach(i=>{var a,_;o[i.id]=(_=(a=r==null?void 0:r.consents[i.id])!=null?a:i.defaultValue)!=null?_:false;}),o});return jsxRuntime.jsx("div",{className:chunkAME4HJR4_js.a("ndpr-consent-banner__options-list",t==null?void 0:t.root,n),"data-ndpr-component":"consent-option-list",children:s.map(o=>jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a("ndpr-consent-banner__option",t==null?void 0:t.optionItem,n),children:[jsxRuntime.jsx("input",{id:`consent-${o.id}`,type:"checkbox",checked:c[o.id]||false,onChange:i=>d(a=>chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},a),{[o.id]:i.target.checked})),disabled:o.required,className:chunkAME4HJR4_js.a("ndpr-consent-banner__option-checkbox",t==null?void 0:t.optionCheckbox,n),"aria-label":o.label}),jsxRuntime.jsxs("div",{className:n?"":"ndpr-consent-banner__option-text",children:[jsxRuntime.jsxs("label",{htmlFor:`consent-${o.id}`,className:chunkAME4HJR4_js.a("ndpr-consent-banner__option-label",t==null?void 0:t.optionLabel,n),children:[o.label,o.required&&jsxRuntime.jsx("span",{className:n?"":"ndpr-consent-banner__required-marker",children:" *"})]}),jsxRuntime.jsx("p",{className:chunkAME4HJR4_js.a("ndpr-consent-banner__option-description",t==null?void 0:t.optionDescription,n),children:o.description})]})]},o.id))})};var R=({children:t,className:n,unstyled:s})=>{let{acceptAll:r}=p();return jsxRuntime.jsx("button",{onClick:r,className:chunkAME4HJR4_js.a("ndpr-consent-banner__button ndpr-consent-banner__button--primary",n,s),"data-ndpr-component":"consent-accept-button",children:t!=null?t:"Accept All"})};var P=({children:t,className:n,unstyled:s})=>{let{rejectAll:r}=p();return jsxRuntime.jsx("button",{onClick:r,className:chunkAME4HJR4_js.a("ndpr-consent-banner__button ndpr-consent-banner__button--secondary",n,s),"data-ndpr-component":"consent-reject-button",children:t!=null?t:"Reject All"})};var y=({children:t,className:n,unstyled:s,consents:r})=>{let{updateConsent:c,options:d}=p();return jsxRuntime.jsx("button",{onClick:()=>{if(r)c(r);else {let i={};d.forEach(a=>{i[a.id]=a.required||false;}),c(i);}},className:chunkAME4HJR4_js.a("ndpr-consent-banner__button ndpr-consent-banner__button--primary",n,s),"data-ndpr-component":"consent-save-button",children:t!=null?t:"Save Preferences"})};var K={Provider:g,OptionList:B,AcceptButton:R,RejectButton:P,SaveButton:y,Banner:chunkPXUX4FYM_js.a,Settings:chunkC32TMS75_js.a,Storage:chunkSJDDNB6M_js.a};Object.defineProperty(exports,"ConsentStorage",{enumerable:true,get:function(){return chunkSJDDNB6M_js.a}});Object.defineProperty(exports,"ConsentManager",{enumerable:true,get:function(){return chunkC32TMS75_js.a}});Object.defineProperty(exports,"ConsentBanner",{enumerable:true,get:function(){return chunkPXUX4FYM_js.a}});Object.defineProperty(exports,"appendAuditEntry",{enumerable:true,get:function(){return chunk3IA3KDII_js.c}});Object.defineProperty(exports,"createAuditEntry",{enumerable:true,get:function(){return chunk3IA3KDII_js.a}});Object.defineProperty(exports,"getAuditLog",{enumerable:true,get:function(){return chunk3IA3KDII_js.b}});Object.defineProperty(exports,"useConsent",{enumerable:true,get:function(){return chunkGJH7YFBO_js.a}});Object.defineProperty(exports,"KNOWN_COOKIES",{enumerable:true,get:function(){return chunkZVWSSXV2_js.c}});Object.defineProperty(exports,"scanCookies",{enumerable:true,get:function(){return chunkZVWSSXV2_js.d}});Object.defineProperty(exports,"validateConsentOptionsStructured",{enumerable:true,get:function(){return chunkZVWSSXV2_js.b}});Object.defineProperty(exports,"validateConsentStructured",{enumerable:true,get:function(){return chunkZVWSSXV2_js.a}});Object.defineProperty(exports,"resolveClass",{enumerable:true,get:function(){return chunkAME4HJR4_js.a}});exports.Consent=K;exports.ConsentAcceptButton=R;exports.ConsentOptionList=B;exports.ConsentProvider=g;exports.ConsentRejectButton=P;exports.ConsentSaveButton=y;exports.useConsentCompound=p;
|
package/dist/consent.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {a}from'./chunk-XOH4WXOZ.mjs';export{a as ConsentStorage}from'./chunk-XOH4WXOZ.mjs';import {a as a$1}from'./chunk-CNCEP66F.mjs';export{a as ConsentManager}from'./chunk-CNCEP66F.mjs';import {a as a$2}from'./chunk-HMKXK23C.mjs';export{a as ConsentBanner}from'./chunk-HMKXK23C.mjs';export{c as appendAuditEntry,a as createAuditEntry,b as getAuditLog}from'./chunk-V7UFP6QU.mjs';import {a as a$3}from'./chunk-
|
|
2
|
+
import {a}from'./chunk-XOH4WXOZ.mjs';export{a as ConsentStorage}from'./chunk-XOH4WXOZ.mjs';import {a as a$1}from'./chunk-CNCEP66F.mjs';export{a as ConsentManager}from'./chunk-CNCEP66F.mjs';import {a as a$2}from'./chunk-HMKXK23C.mjs';export{a as ConsentBanner}from'./chunk-HMKXK23C.mjs';export{c as appendAuditEntry,a as createAuditEntry,b as getAuditLog}from'./chunk-V7UFP6QU.mjs';import {a as a$3}from'./chunk-VXLOPB33.mjs';export{a as useConsent}from'./chunk-VXLOPB33.mjs';import'./chunk-YTU4FNM2.mjs';import'./chunk-XC3DLYEG.mjs';export{c as KNOWN_COOKIES,d as scanCookies,b as validateConsentOptionsStructured,a as validateConsentStructured}from'./chunk-675DXBED.mjs';import {a as a$5}from'./chunk-SFGW37LE.mjs';export{a as resolveClass}from'./chunk-SFGW37LE.mjs';import'./chunk-PHA3YMFO.mjs';import'./chunk-5LJ652AH.mjs';import'./chunk-DBZSN4WP.mjs';import {b,a as a$4}from'./chunk-ZJYULEER.mjs';import {createContext,useContext,useState}from'react';import {jsx,jsxs}from'react/jsx-runtime';var v=createContext(null);function p(){let t=useContext(v);if(!t)throw new Error("Consent compound components must be wrapped in <Consent.Provider>. Example: <Consent.Provider options={...}><Consent.Banner /></Consent.Provider>");return t}var g=({options:t,adapter:n,version:s,onChange:r,children:c})=>{let d=a$3({options:t,adapter:n,version:s,onChange:r}),o=b(a$4({},d),{options:t});return jsx(v.Provider,{value:o,children:c})};var B=({classNames:t,unstyled:n})=>{let{options:s,settings:r}=p(),[c,d]=useState(()=>{let o={};return s.forEach(i=>{var a,_;o[i.id]=(_=(a=r==null?void 0:r.consents[i.id])!=null?a:i.defaultValue)!=null?_:false;}),o});return jsx("div",{className:a$5("ndpr-consent-banner__options-list",t==null?void 0:t.root,n),"data-ndpr-component":"consent-option-list",children:s.map(o=>jsxs("div",{className:a$5("ndpr-consent-banner__option",t==null?void 0:t.optionItem,n),children:[jsx("input",{id:`consent-${o.id}`,type:"checkbox",checked:c[o.id]||false,onChange:i=>d(a=>b(a$4({},a),{[o.id]:i.target.checked})),disabled:o.required,className:a$5("ndpr-consent-banner__option-checkbox",t==null?void 0:t.optionCheckbox,n),"aria-label":o.label}),jsxs("div",{className:n?"":"ndpr-consent-banner__option-text",children:[jsxs("label",{htmlFor:`consent-${o.id}`,className:a$5("ndpr-consent-banner__option-label",t==null?void 0:t.optionLabel,n),children:[o.label,o.required&&jsx("span",{className:n?"":"ndpr-consent-banner__required-marker",children:" *"})]}),jsx("p",{className:a$5("ndpr-consent-banner__option-description",t==null?void 0:t.optionDescription,n),children:o.description})]})]},o.id))})};var R=({children:t,className:n,unstyled:s})=>{let{acceptAll:r}=p();return jsx("button",{onClick:r,className:a$5("ndpr-consent-banner__button ndpr-consent-banner__button--primary",n,s),"data-ndpr-component":"consent-accept-button",children:t!=null?t:"Accept All"})};var P=({children:t,className:n,unstyled:s})=>{let{rejectAll:r}=p();return jsx("button",{onClick:r,className:a$5("ndpr-consent-banner__button ndpr-consent-banner__button--secondary",n,s),"data-ndpr-component":"consent-reject-button",children:t!=null?t:"Reject All"})};var y=({children:t,className:n,unstyled:s,consents:r})=>{let{updateConsent:c,options:d}=p();return jsx("button",{onClick:()=>{if(r)c(r);else {let i={};d.forEach(a=>{i[a.id]=a.required||false;}),c(i);}},className:a$5("ndpr-consent-banner__button ndpr-consent-banner__button--primary",n,s),"data-ndpr-component":"consent-save-button",children:t!=null?t:"Save Preferences"})};var K={Provider:g,OptionList:B,AcceptButton:R,RejectButton:P,SaveButton:y,Banner:a$2,Settings:a$1,Storage:a};export{K as Consent,R as ConsentAcceptButton,B as ConsentOptionList,g as ConsentProvider,P as ConsentRejectButton,y as ConsentSaveButton,p as useConsentCompound};
|
package/dist/core.d.mts
CHANGED
|
@@ -615,6 +615,44 @@ export declare interface ConsentStorageOptions {
|
|
|
615
615
|
};
|
|
616
616
|
}
|
|
617
617
|
|
|
618
|
+
/** How a present cookie was classified. */
|
|
619
|
+
export declare type CookieMatchSource = 'declared' | 'known' | 'none';
|
|
620
|
+
|
|
621
|
+
export declare interface CookieScanOptions {
|
|
622
|
+
/**
|
|
623
|
+
* The cookie string to scan, in `document.cookie` form (`a=1; b=2`).
|
|
624
|
+
* Defaults to `document.cookie` in the browser, or `''` on the server.
|
|
625
|
+
*/
|
|
626
|
+
cookieString?: string;
|
|
627
|
+
/** Reference timestamp (epoch ms) recorded on the result. Defaults to `Date.now()`. */
|
|
628
|
+
asOf?: number;
|
|
629
|
+
/** Extra known cookies, checked before the built-in registry (so they can override it). */
|
|
630
|
+
knownCookies?: DeclaredCookie[];
|
|
631
|
+
/** Whether to fall back to the built-in known-cookie registry for undeclared cookies. @default true */
|
|
632
|
+
useKnownRegistry?: boolean;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
export declare interface CookieScanResult {
|
|
636
|
+
/** When the scan ran (epoch ms). */
|
|
637
|
+
scannedAt: number;
|
|
638
|
+
/** Number of cookies present. */
|
|
639
|
+
total: number;
|
|
640
|
+
/** Every present cookie, classified. */
|
|
641
|
+
cookies: ScannedCookie[];
|
|
642
|
+
/** Cookies that matched one of your declared cookies. */
|
|
643
|
+
declared: ScannedCookie[];
|
|
644
|
+
/** Cookies present but NOT in your declaration — the compliance gap. */
|
|
645
|
+
undeclared: ScannedCookie[];
|
|
646
|
+
/** Undeclared cookies the built-in registry could still identify. */
|
|
647
|
+
identified: ScannedCookie[];
|
|
648
|
+
/** Undeclared cookies that could not be identified at all. */
|
|
649
|
+
unknown: ScannedCookie[];
|
|
650
|
+
/** Present cookies grouped by resolved category; unclassified cookies go under `uncategorized`. */
|
|
651
|
+
byCategory: Record<string, ScannedCookie[]>;
|
|
652
|
+
/** True when there are no undeclared cookies. */
|
|
653
|
+
complete: boolean;
|
|
654
|
+
}
|
|
655
|
+
|
|
618
656
|
/**
|
|
619
657
|
* Creates a new audit entry from consent settings. If `previousSettings` is
|
|
620
658
|
* provided, the action is automatically determined by comparing old and new
|
|
@@ -828,6 +866,30 @@ export declare interface DCPMIThresholds {
|
|
|
828
866
|
*/
|
|
829
867
|
export declare type DCPMITier = 'UHL' | 'EHL' | 'OHL' | 'listed' | 'none';
|
|
830
868
|
|
|
869
|
+
/**
|
|
870
|
+
* Cookie scanner — audits the cookies actually present in the browser against
|
|
871
|
+
* the cookies you have declared, surfacing undeclared cookies that put you out
|
|
872
|
+
* of step with your cookie notice (NDPA 2023 S.25-26 / NDPC GAID 2025 on
|
|
873
|
+
* specific, informed consent).
|
|
874
|
+
*
|
|
875
|
+
* Pure and DOM-optional: pass `cookieString` to scan an arbitrary value (a
|
|
876
|
+
* `Cookie:` header on the server, a test fixture), or call it in the browser
|
|
877
|
+
* and it reads `document.cookie`. Safe to import from a server bundle.
|
|
878
|
+
*/
|
|
879
|
+
/** A cookie you declare against a consent category. */
|
|
880
|
+
export declare interface DeclaredCookie {
|
|
881
|
+
/** Exact cookie name, a prefix (with `prefix: true`), or a RegExp matched against the name. */
|
|
882
|
+
name: string | RegExp;
|
|
883
|
+
/** Consent category this cookie belongs to (e.g. 'necessary', 'analytics', 'marketing'). */
|
|
884
|
+
category: string;
|
|
885
|
+
/** Who sets the cookie (e.g. 'Google Analytics'). */
|
|
886
|
+
provider?: string;
|
|
887
|
+
/** What the cookie is used for — surfaced in your cookie policy. */
|
|
888
|
+
purpose?: string;
|
|
889
|
+
/** Treat a string `name` as a prefix match instead of an exact match. Ignored for RegExp names. */
|
|
890
|
+
prefix?: boolean;
|
|
891
|
+
}
|
|
892
|
+
|
|
831
893
|
/** September 2025 GAID baseline annual fees (NGN). */
|
|
832
894
|
export declare const DEFAULT_DCPMI_FEES_NGN: DCPMIFees;
|
|
833
895
|
|
|
@@ -1323,6 +1385,14 @@ declare type Industry = 'fintech' | 'healthcare' | 'ecommerce' | 'saas' | 'educa
|
|
|
1323
1385
|
*/
|
|
1324
1386
|
export declare function isNDPCApprovalRequired(mechanism: TransferMechanism): boolean;
|
|
1325
1387
|
|
|
1388
|
+
/**
|
|
1389
|
+
* Built-in registry of widely deployed third-party cookies, so an undeclared
|
|
1390
|
+
* cookie can often still be identified (provider + likely category). Override
|
|
1391
|
+
* or extend via {@link CookieScanOptions.knownCookies}; categories follow the
|
|
1392
|
+
* common necessary / functional / analytics / marketing taxonomy.
|
|
1393
|
+
*/
|
|
1394
|
+
export declare const KNOWN_COOKIES: DeclaredCookie[];
|
|
1395
|
+
|
|
1326
1396
|
/**
|
|
1327
1397
|
* Lawful Basis types aligned with NDPA 2023 Part III (Sections 24-28)
|
|
1328
1398
|
* Every processing activity must have a documented lawful basis
|
|
@@ -2330,6 +2400,24 @@ export declare function runNdprAudit(input: NdprAuditInput, options?: NdprAuditO
|
|
|
2330
2400
|
*/
|
|
2331
2401
|
export declare function sanitizeInput(input: string): string;
|
|
2332
2402
|
|
|
2403
|
+
/**
|
|
2404
|
+
* Scan the cookies present against your declared cookies and a registry of
|
|
2405
|
+
* well-known third-party cookies. Returns which cookies are declared, which are
|
|
2406
|
+
* undeclared (and whether they can still be identified), and a per-category view.
|
|
2407
|
+
*/
|
|
2408
|
+
export declare function scanCookies(declared?: DeclaredCookie[], options?: CookieScanOptions): CookieScanResult;
|
|
2409
|
+
|
|
2410
|
+
export declare interface ScannedCookie {
|
|
2411
|
+
/** The cookie name as found in the cookie string. */
|
|
2412
|
+
name: string;
|
|
2413
|
+
/** Resolved consent category, or `null` when it could not be classified. */
|
|
2414
|
+
category: string | null;
|
|
2415
|
+
/** Whether it matched your declaration, only the known registry, or nothing. */
|
|
2416
|
+
matchedBy: CookieMatchSource;
|
|
2417
|
+
provider?: string;
|
|
2418
|
+
purpose?: string;
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2333
2421
|
/**
|
|
2334
2422
|
* Additional conditions required for processing sensitive personal data
|
|
2335
2423
|
* per NDPA Section 30
|