Skip to content

Subprocessors

Verheim's subprocessor list — every vendor in the data path with purpose, data scope, jurisdiction, DPA, and Provisioning status.

Last updated:

Scope of disclosure

This page lists every processor in Verheim's data path: any third party that processes personal data on Verheim's behalf, OR that provides infrastructure on which Verheim runs services that process personal data. Verheim publishes this list under NFR-I1 ("every integration vendor processing personal data on Verheim's behalf appears in the published subprocessor list") and NFR-Pr1 (GDPR Art. 28 transparency).

Self-hosted analytics and synthetic monitoring services on Verheim's own infrastructure are explicitly disclosed in the table below but flagged as "not a third-party subprocessor" because they run in-house on Verheim's own VPS, not on third-party infrastructure. The underlying VPS provider is itself listed in the table as a separate row — listing the in-house service does not double-count, it discloses the named service.

At the date of this revision, Verheim's production data path is in the Phase-C provisioning window: the origin VPS, the domain and TLS registration, the CDN pull-zones, the Git-hosted CI gates, and the no-JS smoke required-check are each operator- bound provisioning steps that have not yet completed. The published list discloses the planned data-path graph; the actual data path tracks toward the published list as each step lands. Each row's Provisioning status column makes the planned-vs-active state structurally readable so the page reads honestly at any provisioning state. NFR-Pr4 names a discrepancy between the published list and the actual data path as a notifiable incident — the published list is therefore the disclosure-of-record at every point in time.

Subprocessor table

Subprocessor Purpose Data scope Jurisdiction DPA Provisioning status
Hetzner Origin hosting, Gitea, isolated Actions runner, backups Site source, build artifacts, system logs, IP for rate-limiting, encrypted backups Germany (DE) DPA for Hetzner (opens in a new tab) Planned (D001 pending)
Bunny.net CDN, preview pull-zones, Bunny Shield WAF Cached site content, IP for edge routing EU-only routing (multi-EU PoPs) DPA for Bunny.net (opens in a new tab) Planned (D003 pending)
Gandi DNS authority, domain registrar Domain registration data, DNS query logs France (FR) DPA for Gandi (opens in a new tab) Planned (D002 pending)
Let's Encrypt (ISRG) TLS certificate issuance Public domain names; no personal data USA (ISRG headquartered US; certificates issued globally) DPA for Let's Encrypt (ISRG) (opens in a new tab) Planned (D002 pending)
Brevo Transactional email primary (form-submission acknowledgments, admin notifications) Recipient email, form submission contents France (FR) DPA for Brevo (opens in a new tab) Planned (Epic 4 pending)
Scaleway TEM Transactional email fallback Recipient email, form submission contents France (FR) DPA for Scaleway TEM (opens in a new tab) Planned (Epic 4 pending)
URIports DMARC, SMTP-TLS, MTA-STS aggregator Email-authentication aggregate reports (no personal data) Netherlands (NL) DPA for URIports (opens in a new tab) Planned (Story 3.6 pending)
Hetzner Storage Box Off-site encrypted backups Encrypted backups of site sources, build artifacts, audit logs Finland (FI) or Germany (DE) DPA for Hetzner Storage Box (opens in a new tab) Planned (D001 pending)
Plausible Community Edition Web analytics Page views, referrer, user-agent (per ADR-004 zero-PII contract) Self-hosted on Hetzner — not a third-party subprocessor n/a (in-house instance) Self-hosted on Hetzner — not a third-party subprocessor
Uptime Kuma Synthetic monitoring Site uptime probes (no personal data) Self-hosted on Hetzner — not a third-party subprocessor n/a (in-house instance) Self-hosted on Hetzner — not a third-party subprocessor

All third-party subprocessors processing personal data are EU-resident; Let's Encrypt (US-incorporated) processes non-personal data only and is included for completeness per NFR-I1.

Schrems II posture

Verheim operates an EU-resident data path. NFR-Pr4 binds Verheim to "no US-processor in the data path for form submissions, analytics, or hosting without documented supplementary measures". Every personal-data-processing vendor in the table above is EU-resident: Hetzner (DE), Bunny.net (EU-only routing across multi-EU PoPs), Gandi (FR), Brevo (FR), Scaleway TEM (FR), URIports (NL), Hetzner Storage Box (FI/DE).

Let's Encrypt (operated by ISRG, US-incorporated) processes non-personal data only — public domain names submitted for TLS certificate issuance — and is therefore disclosed for completeness per NFR-I1 without requiring Schrems II supplementary measures. The carve-out is named on the row in the table above and again in the editorial note that follows the table.

The controller-side disclosure of the same Schrems II contract appears on Verheim's privacy policy under its Transfer posture section. Procurement reviewers and EU regulators may correlate the two disclosures: the privacy policy describes the contractual posture; this page describes the per-vendor implementation.

Vendor-addition discipline

Adding a vendor to Verheim's data path is gated on a documented review process. Per the contract recorded in config/security/external-hostnames.txt, vendor additions require:

  1. A pull request via .gitea/PULL_REQUEST_TEMPLATE/external-hostname.md capturing vendor name + DPA URL + data categories + Schrems II posture + the config/security/external-hostnames.txt commit reference;
  2. CODEOWNERS approval from the @verheim/security AND @verheim/privacy reviewer groups; AND
  3. A simultaneous edit of config/security/csp-directives.txt if the vendor is fetched at runtime from a browser session, plus a simultaneous edit of src/config/subprocessors.ts so this page reflects the addition.

The PR template and CODEOWNERS routing assets are themselves operator-bound on Verheim's Gitea provisioning. Pre-Gitea- landing, the discipline is honoured editorially via PR description prose mirroring the template fields; post-Gitea- landing, the assets are authored in a coordinated patch alongside the Gitea provisioning step.

Drift-incident contract

A discrepancy between Verheim's actual data path and this published subprocessor list is an incident under NFR-Pr4 and triggers the breach-notification process if personal data is affected. Subprocessor-list update is therefore a mandatory pre-flight step whenever a new vendor enters the data path — the published list must always lead the actual deployment, not trail it.

Drift-detection runs on two channels:

  • Automated dist-scan — Story 1.15 ships a build-time scan that compares every external hostname referenced in dist/ against the config/security/external-hostnames.txt allowlist. This catches runtime-fetched hostname drift (e.g. a third-party script or font URL slipping into the bundle without the corresponding allowlist + subprocessor-list update).
  • Manual review — at vendor-addition time and at every retrospective, an operator reviews the actual data path against this list. Manual review is the only mechanism that catches non-runtime vendor drift (Hetzner origin, Brevo SMTP relay, Hetzner Storage Box backups — vendors whose URLs do not appear in dist/).

The operational playbook for a confirmed drift incident is Verheim's docs/operators/runbooks/incident-subprocessor-drift.md runbook — registered at architecture.md:866 and authored under the Epic-9 incident-runbook batch. The runbook codifies detection, immediate response (subprocessor list update + GDPR Art. 33/34 breach-notification consideration if PII-affected), and recovery.

Last revision

Last revision: 0440a2a (opens in a new tab) on . The short SHA is the audit-trail value: it pins this published list to a Git commit in Verheim's repository so an EU regulator or procurement reviewer can verify which revision of the list they are reading. The Date matches the page's publication date; the SHA may differ if a post-publication patch updates the page without re-dating the publication.