Changelog
Full version-by-version changelog of the Digital Sovereignty Heatmap.
Inhoud in het Engels — pagina-navigatie blijft Nederlands.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[0.2.0] - 2026-05-26
On-site changelog
- New
/[locale]/changelogpage (NL + EN) rendering the user-facing update history. Source of truth:apps/web/src/lib/changelog.ts(typed, kept separate from this technical CHANGELOG.md). - Footer badge "Bijgewerkt:
" / "Updated: " on every page, sourced from the latest changelog entry, linking to /changelog. /changelogadded tositemap.xmlwith NL/EN hreflang alternates.
Vendor-database review — 2026-05-26
Net result: 1679 → 1700 vendor records. Source of truth: apps/web/data/vendors.seed.json. One-shot migration script: apps/web/scripts/migrate-vendors-2026-05.ts.
Added
- Schema fields on
Vendor(additive, non-breaking):ultimate_parent_country(optional ISO-2),sovereignty_mode(vendor-hosted-eu/self-host/oss-distributed/vendor-hosted-non-eu),eu_classification(eu-strict/eea/efta/eu-adjacent). Back-filled for all existing records. - 27 new EU vendors: CMP (Didomi, Axeptio, consentmanager.net) — SMS (TextMagic, SMSAPI) — Monitoring (Dynatrace, Pandora FMS) — Time tracking (TimeCamp, TimeTac) — Low-code (Make.com, Ninox, SeaTable) — Marketing (MailerLite) — CMS (Hygraph) — Translation (memoQ, Phrase TMS, Wordbee, Across) — Fintech (Trade Republic) — Helpdesk (Aircall) — Healthcare (Nedap Healthcare) — AI coding (JetBrains AI Assistant) — Notes (Bear) — Scheduling (Pretix, Bookingkit) — Enterprise social (LumApps, Talkspirit).
- Invariant test suite vendor-invariants.test.ts — 9 tests pinning: no
EUsentinel HQ without explicitsovereignty_mode, no >2 categories without allow-list, no duplicate(name, category)pairs, no Dutch' or 'translation-bug pattern indescription_en, ISO-3166-1 alpha-2 country codes, HTTPS-only websites, and the May-2026 problem-record outcomes. - ADR-001 — policy for borderline EU-provenance vendors (Optimizely, Sitecore, Talkdesk, Dashlane, Revolut, Yubico).
Changed (corrected HQs)
- Hologic, Carestream Health, Wrike, WordPress (self-host) reclassified EU → US. Wrike now carries
ultimate_parent_country=US(Symphony Industrial). - RustDesk → CN with
sovereignty_mode=oss-distributed. Logseq → SG,oss-distributed. Synology Drive (on-prem) → TW,self-host. - Bitrix24 → CY with
ultimate_parent_country=RUdisclosed in description. - Wire (both collaboration + messaging records) corrected to CH,
eu_classification=efta. - Directus → US (
ultimate_parent_country=US,sovereignty_mode=self-host); the duplicate cms-categorised record was removed in favour of the low-code entry. - SumUp → GB with
eu_classification=eu-adjacent; the duplicatesumup-paymentsrecord removed. - European-classification tags rolled out: 57 Swiss vendors →
efta, 29 Norwegian/Icelandic →eea, 4 Ukrainian →eu-adjacent, 1159 EU-27 →eu-strict.headquarters_regionleft atEUdeliberately so the scoring engine (10+=== "EU"checks across dimensions, drivers, migration, suggestions) keeps its current behaviour.
Removed
epic-eu(real HQ Verona WI —epic-ehrUS incumbent retained)sumup-payments(merged intosumup)directuscms-variant (merged intodirectus-lowcode)soffos-office(duplicate ofsoftmaker-officein the same category)adyenandmolliefromerp-finance— payments processors, not ERPs. Both still listed underpayments(ande-commercefor Adyen).
Earlier under [Unreleased]
Added
- New category: writing-tools (Schrijfhulp & Grammatica) with LanguageTool as EU alternative
- New vendors: Backblaze (storage-backup), Grammarly (writing-tools), Luminar Neo (design)
- EU alternative mappings for Backblaze, Grammarly, and Luminar Neo
Fixed
- Pinned
aquasecurity/trivy-actionto@0.30.0(was@master— supply chain risk) - Dockerfile: resilient native addon copy handles pnpm hoisting variations
- Defensive JSON parsing in
mapVendorRow(try/catch instead of bareJSON.parse) - Map and Alternatives pages: added error state with retry button (was silent failure)
- Accessibility: added
aria-labelto map country panel close button - Copy: consistent Dutch wording in map disclaimer
Security
- Red-team review completed: PASS across all 5 perspectives (architecture, security, test quality, devops, UX)
- No blockers found; 4 majors identified and remediated
- Full findings documented in REVIEW.md
[0.1.0] — Unreleased
Added
- Vendor expansion: ~130 vendors across 20 categories (was ~105 in 16)
- 4 new categories: Projectmanagement (business), Muziek streaming, Video streaming, Notities & taken (personal)
- ~24 new vendors: project management (OpenProject, Taiga, Plane, Jira, Confluence, Notion, Linear, Asana), music streaming (Deezer, Spotify, Tidal, Apple Music, YouTube Music), video streaming (NLZIET, NPO Start, Netflix, YouTube, Disney+), notes & tasks (Joplin, Standard Notes, Obsidian, Apple Notes, Google Keep), plus LinkedIn, Instagram, TikTok (social media) and Safari (browser)
- Direct vendor recommendations: concrete "Gmail → Stap over naar Tuta" suggestions with specific Dutch-language reasons per vendor
VendorRecommendationinterface andgenerateVendorRecommendations()in@ds-heatmap/coreRecommendationListcomponent for rendering recommendations in results- Personal block: 8 new personal categories (E-mail, Messaging, Cloud Storage, VPN, Password Manager, Browser, Social Media, Desktop OS)
- Separate scoring: business and personal assessments computed and displayed independently
- 2 new personal scenarios: Privé Soeverein, Privé Hybride
blockfield on Category schema ("business"|"personal")DEFAULT_PERSONAL_CATEGORY_WEIGHTSandCRITICAL_PERSONAL_CATEGORIES- Database migration for existing DBs (adds
blockcolumn)
Changed
- Recommendation system: replaced abstract driver-level suggestions with direct per-vendor recommendations
- Removed
DriverSuggestiontype,suggestionsfield onDriver, andenrichDriversWithSuggestions() - Business category weights renormalised for 9 categories (added project-management at 0.066)
- Personal category weights redistributed for 11 categories (equal ~0.0909 each)
notes-tasksadded toCRITICAL_PERSONAL_CATEGORIES- Wizard vendor selection split into "Zakelijk" and "Privé" sections
- Results page shows separate score panels per block with recommendation section
- Existing business scenarios updated with new vendors
- Telemetry allowlist expanded with all new vendor and category slugs
[0.1.0] - 2026-02-27
Added
- Three-step assessment wizard: vendor selection → context → results with animated transitions
- Deterministic scoring engine: 5 sovereignty dimensions (JES, DRS, CKS, PLS, SRS), category-weighted aggregation, risk drivers
- Vendor knowledgebase with SQLite (better-sqlite3) — 32 vendors, 8 categories, 3 scenarios
- Zod schemas for Category, Vendor, and Scenario in
@ds-heatmap/core - API routes:
GET /api/vendors,GET /api/categories,GET /api/scenarios,GET /api/health - Vendor filtering by category (
?category=) and search (?q=) - Auto-seeding: database is seeded from JSON on first access
- CLI seed script:
pnpm seed/pnpm seed --force - Board memo generation: "Genereer bestuursmemo" button on results page → POST
/api/memo→ print-friendly/memopage - Dutch-language deterministic template with score-dependent executive summary, risk drivers, and recommendations
- Optional Claude AI integration (
CLAUDE_ENABLED=true) with automatic fallback to template - In-memory token-bucket rate limiter for
/api/memo(5 burst, 1/10s refill per IP) - Print/PDF-friendly layout with
@media printstyles (A4) - Privacy-preserving telemetry: aggregated counters only, no raw events or PII stored
- Telemetry disabled by default (
TELEMETRY_ENABLED=false); double opt-in (server + user) - Strict allowlist validation: event names, vendor/category slugs, context enums, score bands (0-33/34-66/67-100)
/trendspage with k-anonymous community data (buckets < K_ANON_THRESHOLD grouped as "Other")- Footer telemetry toggle with clear privacy copy
POST /api/telemetryendpoint with rate limiting and Zod validationGET /api/trendsendpoint with k-anonymity filtermetrics_countersSQLite table for aggregated counter storage- Release workflow: tag → build + Trivy scan → push to GHCR → GitHub Release with CHANGELOG notes
- Structured JSON logger for server-side components
- Initial project scaffold: Next.js 15 (App Router) + TypeScript + Tailwind CSS + shadcn/ui
- pnpm monorepo with
apps/webandpackages/core - Multi-stage Dockerfile with non-root runtime user
- Docker Compose with Caddy reverse proxy (auto-HTTPS capable)
- GitHub Actions CI: lint, typecheck, test, build, Trivy scan, gitleaks, dependency audit
Security
- Next.js middleware with security headers: CSP, X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policy, Permissions-Policy
- Request body size limits on all POST endpoints (16 KB for memo, 2 KB for telemetry)
- Rate limiting per client IP on POST endpoints (in-memory token bucket)
- Zod schema validation on all POST request bodies
- Docker: read-only filesystem, resource limits (512 MB / 1 CPU), restrictive data directory permissions (750)
- OCI image labels for GHCR metadata
- No prompt payloads logged in Claude integration
- No PII stored in telemetry (counters only, no IPs, no sessions)