Files
ukmesh/docs/privacy.md
T

72 lines
3.8 KiB
Markdown

# Privacy & data retention
Applies to ukmesh.com / app.ukmesh.com (MeshCore Analytics). UK GDPR + DPA 2018.
Contact: ukmesh@proton.me
## 1. Error diagnostics telemetry
**What is stored** (per event): kind (error/warning/unhandledrejection/crash),
truncated message (≤500 chars) and stack (≤4000 chars), page pathname only (no
query string), userAgent, HMAC-hashed source IP. No raw IPs, no account IDs,
no cookies, no localStorage in the telemetry path.
**Lawful basis — legitimate interest (Art 6(1)(f)).** Three-part test:
- **Purpose test:** operating a reliable public service requires knowing when
client-side failures occur; this telemetry has already root-caused real
production crashes (deck.gl/maplibre, worker-file MIME regressions).
- **Necessity test:** error capture cannot be tied to a logged-in account
(the site has no general auth), so pseudonymous event capture is the
minimum effective means; fields are bounded and truncated.
- **Balancing test:** data is pseudonymous (hashed IP, no identifiers), kept
30 days, rate-limited (10/min/IP) and sampled (20/hr/source), self-hosted
(no third-party processor → no DPA required), no profiling. Individual
impact is minimal; service reliability benefit is direct.
**Retention:** 30 days, enforced by the operational retention loop
(`DATA_LIFECYCLE_RETENTION_ENABLED=true` + `DATA_LIFECYCLE_RETENTION_TARGETS`).
**Erasure:** individuals cannot be mapped to rows; the retention job IS the
erasure mechanism (documented as such).
## 2. Mesh packet database
The service stores radio traffic observed on the MeshCore network.
| Data | Retained | Rationale |
|---|---|---|
| `packets` — message content + raw bytes + metadata | **at most 30 days** (Timescale chunk policy + bounded exact-row boundary cleanup) | network diagnostics; content is not kept long-term |
| `packet_decryptions` — full decrypted messages | **30 days** (operational retention loop) | diagnostics only |
| `packet_paths` — path metadata (node IDs, timing, signal, hashes) | **indefinite, content-stripped** | raw pathing analytics is the product |
| `multibyte_path_facts`, `multihop_paths_weekly`, `path_*_priors` — derived path stats | indefinite | derived, pseudonymous |
| `packet_daily_stats` / `packet_hourly_stats` | indefinite | anonymous aggregates |
**Lawful basis — legitimate interest (Art 6(1)(f)).**
- **Purpose test:** operating and improving the network (pathing, coverage,
diagnostics) requires the packet data; the owner portal requires status data.
- **Necessity test:** content is deleted after 30 days; long-term retention is
limited to path metadata with no message content and no coordinates, which
is the minimum needed for pathing analytics.
- **Balancing test:** pseudonymous node identifiers only (linkable to an
individual solely when a node owner registers in the portal); no content in
long-lived tables; no individual profiling; disclosed in the privacy notice.
**Design rules (binding):**
- Path/long-lived tables NEVER gain `payload`, `raw_hex`, or coordinate
columns. Content-bearing tables always have a retention policy.
- Retained path visibility is derived from the current private-node prefix
tables. Stored `packet_paths` flags are a trigger-maintained cache and are
never the authority for a public or derived read.
- Decryption outputs land only in short-retention tables (30 days).
- New derived tables get a lifecycle policy at creation.
- Erasure (Art 17): owner-portal-linked nodes are mappable — node-scoped
deletion procedure in the ops playbook (rows by src/rx node id across
packets, packet_paths, decryptions, path facts).
## 3. Cookies
LocalStorage-only choices (cookie consent, theme). No third-party cookies.
PECR does not apply to the mesh radio data (not a public electronic
communications network).