Skip to content

Commit 5a5b7af

Browse files
authored
Merge pull request #39 from SimplyLiz/develop
Release 1.0.1
2 parents 11ceaf8 + f876694 commit 5a5b7af

13 files changed

Lines changed: 367 additions & 46 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 1.0.1 (2026-03-04)
4+
5+
### Documentation
6+
7+
- **Privacy documentation** — Added `PRIVACY.md` and dedicated privacy guide (`docs/privacy.md`) with signal inventory, cookie details, fingerprinting risk assessment, consent integration examples, data subject rights, and regulatory guidance (GDPR, ePrivacy, CCPA, LGPD)
8+
39
## 1.0.0 (2026-03-04)
410

511
### Breaking Changes

PRIVACY.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Privacy
2+
3+
DeviceRouter collects device capability signals to classify devices and derive rendering hints.
4+
This document summarizes what is collected, what is not, and where to find detailed guidance.
5+
6+
## What is collected
7+
8+
The client probe reads the following signals via browser APIs:
9+
10+
- CPU core count (`hardwareConcurrency`)
11+
- Device memory (`deviceMemory`)
12+
- Connection type, downlink speed, RTT, data saver mode (`navigator.connection`)
13+
- Pixel ratio (`devicePixelRatio`)
14+
- Prefers reduced motion / color scheme (`matchMedia`)
15+
- GPU renderer (WebGL debug info)
16+
- Battery level and charging status (`navigator.getBattery()`)
17+
18+
All signals are optional — the probe gracefully degrades based on what the browser supports.
19+
20+
## What is NOT stored
21+
22+
- **User agent** — collected for bot/crawler filtering, then stripped before storage
23+
- **Viewport dimensions** — collected for bot/crawler filtering, then stripped before storage
24+
25+
These two fields never reach the storage layer.
26+
27+
## Cookie
28+
29+
DeviceRouter sets a single session cookie:
30+
31+
| Attribute | Value |
32+
| ---------- | ----------------------- |
33+
| Name | `device-router-session` |
34+
| `httpOnly` | `true` |
35+
| `sameSite` | `lax` |
36+
| `secure` | `false` (configurable) |
37+
| `path` | `/` (configurable) |
38+
| Max age | 24 hours (configurable) |
39+
40+
The cookie value is a random UUID v4 (`crypto.randomUUID()`). It contains no user data — it is
41+
solely a key to look up the stored device profile.
42+
43+
## No tracking, no profiling
44+
45+
- Profiles are tied to random session tokens, not to users or accounts
46+
- No data is shared with third parties
47+
- No cross-session or cross-site tracking
48+
- No personally identifiable information (PII) is collected or stored
49+
50+
## Regulatory implications
51+
52+
Depending on your jurisdiction, collecting device signals and setting a cookie may require user
53+
consent. DeviceRouter provides the technical building blocks but does **not** include a consent
54+
mechanism — that is your responsibility.
55+
56+
For detailed regulatory guidance (GDPR, ePrivacy, CCPA, LGPD) and consent integration examples,
57+
see the [Privacy Guide](docs/privacy.md).
58+
59+
---
60+
61+
> **Disclaimer:** This document is informational guidance, not legal advice. Consult a qualified
62+
> privacy professional for your specific deployment.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ Open http://localhost:3000 — the probe runs on first load, refresh to see your
268268
## Documentation
269269

270270
- [Getting Started](docs/getting-started.md)
271+
- [Privacy Guide](docs/privacy.md) — Signal inventory, cookie details, consent integration, GDPR/CCPA/LGPD guidance
271272
- [Observability](docs/observability.md) — Logging, metrics, and monitoring hooks
272273
- [Deployment Guide](docs/deployment.md) — Docker, Cloudflare Workers, serverless
273274
- [Meta-Framework Integration](docs/meta-frameworks.md) — Next.js, Remix, SvelteKit

docs/getting-started.md

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -306,45 +306,9 @@ const storage = new RedisStorageAdapter({
306306

307307
## Privacy and Cookie Consent
308308

309-
DeviceRouter collects device capability signals (CPU cores, memory, GPU renderer, viewport, connection type, battery status, user agent) and links them to a session cookie. Depending on your jurisdiction, this has regulatory implications.
309+
DeviceRouter collects device capability signals and links them to a session cookie. Depending on your jurisdiction (EU, UK, California, Brazil, and others), this has regulatory implications — you may need to obtain user consent before loading the probe script.
310310

311-
### Collected signals and fingerprinting
312-
313-
The signals DeviceRouter collects overlap with known browser fingerprinting vectors. Regulators evaluate the _capability_ of the data to identify users, not just the stated intent. Even though DeviceRouter uses these signals solely for adaptive rendering, the combination of GPU renderer, hardware concurrency, device memory, viewport, and user agent can narrow down device identity — and regulators treat that as personal data.
314-
315-
### EU: GDPR and ePrivacy Directive
316-
317-
Two regulations apply independently:
318-
319-
- **ePrivacy Directive (Article 5(3))** covers both setting the `device-router-session` cookie _and_ reading device signals from browser APIs. Both count as accessing information stored on terminal equipment. The "strictly necessary" exemption is interpreted narrowly by the EDPB, CNIL, and ICO — it requires that the service _cannot function_ without the data, not that it functions _better_ with it. Adaptive rendering has not been recognized as strictly necessary by any regulator.
320-
321-
- **GDPR** applies because the collected signals in aggregate constitute personal data (Recital 30 explicitly references device identifiers and the profiles they can create). You need a lawful basis under Article 6 — consent (Article 6(1)(a)) is the most defensible option.
322-
323-
**In practice:** implement a cookie consent mechanism before deploying DeviceRouter in the EU.
324-
325-
### UK
326-
327-
The UK GDPR and PECR follow the same framework as the EU. The ICO has been particularly vocal about fingerprinting-like techniques — treat the requirements as equivalent.
328-
329-
### California (CCPA/CPRA)
330-
331-
The collected signals qualify as personal information under CCPA. You must:
332-
333-
- Disclose the collection in your privacy notice (notice at collection)
334-
- Honor access and deletion requests for stored profiles
335-
- If you never sell or share the data with third parties, the "Do Not Sell" opt-out does not apply, but the data is still subject to consumer rights
336-
337-
### Brazil (LGPD)
338-
339-
The ANPD treats cookie and fingerprinting data as personal data. Consent must be "free, informed and unequivocal." There is no "strictly necessary" carve-out equivalent to the ePrivacy Directive.
340-
341-
### Recommendations
342-
343-
- Obtain consent before loading the probe script in jurisdictions that require it
344-
- Include DeviceRouter's signal collection in your privacy policy
345-
- Set a reasonable TTL — shorter sessions reduce the regulatory surface
346-
- Use `MemoryStorageAdapter` or configure Redis key expiration so profiles are not retained beyond their useful life
347-
- Consider omitting high-entropy signals you do not need (e.g., if you only need CPU/memory tiers, you may not need `gpuRenderer` or `battery`)
311+
For a full signal inventory, fingerprinting risk assessment, cookie details, consent integration examples, and jurisdiction-specific guidance, see the [Privacy Guide](privacy.md).
348312

349313
> **Note:** This section is informational guidance, not legal advice. Consult a qualified privacy professional for your specific deployment.
350314

0 commit comments

Comments
 (0)