{
  "policy_version": "2026-06-25",
  "generated_at": "2026-06-29T00:43:11.954Z",
  "controller": {
    "name": "Gilanpour Development AB (org. nr 559265-4676)",
    "contact_email_placeholder": "https://ventreport.com/contact"
  },
  "subprocessors": [
    {
      "id": "supabase",
      "name": "Supabase",
      "service": "Managed Postgres database hosting + connection pooling",
      "data_locations": [
        "SE"
      ],
      "transfer_mechanism": "EU/EEA",
      "status": "active",
      "privacy_policy_url": "https://supabase.com/privacy",
      "notes": "Project hosted in eu-north-1 (Stockholm). All customer data — Sites, Inspections, Measurements, CleaningReports, User accounts, Companies — lives in this Postgres instance."
    },
    {
      "id": "vercel",
      "name": "Vercel",
      "service": "Application hosting (Next.js runtime + edge network)",
      "data_locations": [
        "DE",
        "FR",
        "IE"
      ],
      "transfer_mechanism": "EU/EEA",
      "status": "planned",
      "privacy_policy_url": "https://vercel.com/legal/privacy-policy",
      "notes": "Production deployment is configured to use Frankfurt / Paris / Dublin edge regions only. Disclosure listed as 'planned' until production launch flips it to 'active'."
    },
    {
      "id": "cloudflare-r2",
      "name": "Cloudflare R2",
      "service": "Object storage for cleaning-report PDFs, schematic uploads, photos, user signature images",
      "data_locations": [
        "EU"
      ],
      "transfer_mechanism": "EU/EEA",
      "status": "planned",
      "privacy_policy_url": "https://www.cloudflare.com/privacypolicy/",
      "notes": "Bucket location set to EU jurisdiction (replicated across EU data centres). Phase 3d wires this up; until then, file uploads are not yet active. Pre-signed PUT URLs are used for direct browser → R2 upload with content-hash addressing."
    },
    {
      "id": "sentry",
      "name": "Sentry",
      "service": "Application error & performance monitoring (crash / exception reporting for the server, edge, and browser runtimes)",
      "data_locations": [
        "EU"
      ],
      "transfer_mechanism": "EU/EEA",
      "status": "planned",
      "privacy_policy_url": "https://sentry.io/privacy/",
      "notes": "EU data region — events are ingested via *.ingest.de.sentry.io and stored within the European Union. Captures error stack traces and minimal request context to diagnose faults; personal data is scrubbed before send (sendDefaultPii is off and a beforeSend hook strips cookies, authorization headers, request bodies, query strings and user identifiers — only the URL path is retained). No customer compliance data is sent. Listed as 'planned' until the production DSN is configured at launch — until then the SDK is a no-op and transmits nothing."
    },
    {
      "id": "cloudflare-turnstile",
      "name": "Cloudflare Turnstile",
      "service": "Bot-protection captcha widget on the public /contact form. Verifies that a real user (not an automated script) submitted the form.",
      "data_locations": [
        "EU",
        "US"
      ],
      "transfer_mechanism": "SCCs + supplementary measures",
      "status": "active",
      "privacy_policy_url": "https://www.cloudflare.com/privacypolicy/",
      "notes": "Loaded only on /contact (lazy-loaded on first form interaction). The widget collects browser signals (IP address, User-Agent, mouse / key input timing, and minimal browser-fingerprint data) and sends them to Cloudflare for the bot-or-human decision. Distinct from Cloudflare R2: different product, different data flow, different endpoint (challenges.cloudflare.com). Functional necessity for the anti-spam stack — does NOT require visitor consent under the CMP (strictly-necessary category), but is disclosed here for full transparency per GDPR Art. 13."
    },
    {
      "id": "resend",
      "name": "Resend",
      "service": "Transactional email (magic-link sign-in, reminder emails, DSAR export delivery)",
      "data_locations": [
        "EU"
      ],
      "transfer_mechanism": "EU/EEA",
      "status": "planned",
      "privacy_policy_url": "https://resend.com/legal/privacy-policy",
      "notes": "EU region. Recipient email + email content (the magic-link URL or reminder body) is shared with Resend for delivery only; no other personal data is transmitted."
    },
    {
      "id": "google-oidc",
      "name": "Google",
      "service": "Google OIDC sign-in (only if the user chooses 'Sign in with Google')",
      "data_locations": [
        "US"
      ],
      "transfer_mechanism": "SCCs + supplementary measures",
      "status": "conditional",
      "privacy_policy_url": "https://policies.google.com/privacy",
      "notes": "Only triggered when a user voluntarily uses Google as their identity provider. The OIDC handshake exchanges Google's user-id token for a VentReport session. No customer data is sent to Google. US transfers rely on EU-US Data Privacy Framework adequacy + SCCs for redundancy."
    },
    {
      "id": "google-analytics",
      "name": "Google Analytics (gtag.js)",
      "service": "Anonymised page-view + user-flow analytics. Loads only after the visitor accepts the 'analytics' category in the cookie consent banner.",
      "data_locations": [
        "US"
      ],
      "transfer_mechanism": "SCCs + supplementary measures",
      "status": "conditional",
      "privacy_policy_url": "https://policies.google.com/privacy",
      "notes": "Consent-gated: gtag.js does not load until the visitor explicitly accepts analytics in the CMP banner. EDPB 5/2020 default-deny posture. Visitors who decline or haven't decided are not tracked. The gtag snippet sets cookies (_ga, _ga_<container>) under the ventreport.com domain. Toggle off in Cookie preferences uses Consent Mode v2 to halt further sends mid-session."
    },
    {
      "id": "cloudflare-web-analytics",
      "name": "Cloudflare Web Analytics",
      "service": "Cookie-free aggregate web analytics (page views, traffic sources). Loads only after the visitor accepts the 'analytics' category in the cookie consent banner.",
      "data_locations": [
        "EU",
        "US"
      ],
      "transfer_mechanism": "SCCs + supplementary measures",
      "status": "conditional",
      "privacy_policy_url": "https://www.cloudflare.com/privacypolicy/",
      "notes": "Consent-gated. Cloudflare Web Analytics is intentionally cookie-free and aggregates everything server-side; there are no per-user identifiers, no cross-site tracking, no fingerprinting. Beacon URL: static.cloudflareinsights.com/beacon.min.js. The single 'analytics' CMP toggle covers GA, Cloudflare, and Clarity together."
    },
    {
      "id": "microsoft-clarity",
      "name": "Microsoft Clarity",
      "service": "Session replay + heatmap analytics. Records anonymised mouse / scroll / click sequences with input fields masked by default. Loads only after the visitor accepts the 'analytics' category in the cookie consent banner.",
      "data_locations": [
        "US"
      ],
      "transfer_mechanism": "SCCs + supplementary measures",
      "status": "conditional",
      "privacy_policy_url": "https://privacy.microsoft.com/privacystatement",
      "notes": "Consent-gated. Clarity exposes a consent API (`clarity('consent', true|false)`) that pauses or resumes data collection without unloading the script — used to drive mid-session toggles via the CMP modal. Default PII masking covers form inputs; we do not explicitly opt in to recording inputs. Tag URL: www.clarity.ms/tag/<project-id>. Most invasive of the three analytics tools we use, so consent gating is non-negotiable."
    },
    {
      "id": "microsoft-entra",
      "name": "Microsoft (Entra ID)",
      "service": "Microsoft OIDC sign-in (only if the user chooses 'Sign in with Microsoft')",
      "data_locations": [
        "EU",
        "US"
      ],
      "transfer_mechanism": "SCCs + supplementary measures",
      "status": "conditional",
      "privacy_policy_url": "https://privacy.microsoft.com/privacystatement",
      "notes": "Same rationale as Google. EU-tenant Entra deployments stay in EU; global tenants may route through US. SCCs cover the residual transfer."
    },
    {
      "id": "anthropic",
      "name": "Anthropic",
      "service": "AI model provider for the in-app support assistant (chatbot) and the translation tooling used to maintain the platform's localised copy. When a user sends a message to the assistant, the message and the relevant conversation context are processed by Anthropic's Claude API to generate the reply. The translation tooling sends source strings (platform copy, not customer data) to the same API.",
      "data_locations": [
        "US"
      ],
      "transfer_mechanism": "SCCs + supplementary measures",
      "status": "active",
      "privacy_policy_url": "https://www.anthropic.com/legal/dpa",
      "notes": "Triggered when a user interacts with the support assistant. The user's typed messages, and — for signed-in users — concise summaries of their own VentReport records retrieved to answer their questions, are sent to Anthropic's API. No bulk customer data is sent — only the active conversation. Under Anthropic's standard Data Processing Addendum (https://www.anthropic.com/legal/dpa) API inputs and outputs are NOT used to train Anthropic's models, prompts are retained for up to 30 days for trust-and-safety (abuse-prevention) purposes before deletion, and zero-retention can be requested in writing for specific use cases. Hosted in the United States; transfers covered by the EU Commission's Standard Contractual Clauses (Module 2) plus a Schrems II Transfer Impact Assessment."
    }
  ]
}