Privacy policy — Kaderlab EU Compliance Kit
1. Who we are
Kaderlab EU Compliance Kit is built and operated by AVS Digital, a Dutch one-person business (eenmanszaak) trading as Kaderlab, KvK 67123783, Amsterdam, the Netherlands.
Write to support@kaderlab.com about anything in this document, including a request to see, correct or erase what the app holds about your shop.
Kaderlab is one person plus automation, and says so. This app is built and operated day to day with the help of AI automation. No part of the app talks to a shopper, and nothing in it generates text that a shopper reads: the words in every storefront notice are the merchant's own.
2. Which app this is about
This document covers the Shopify app Kaderlab EU Compliance Kit and the Cloudflare Worker behind it. It does not cover a merchant's own shop, their theme, or anything else Kaderlab publishes.
3. What the app stores
The app stores shop-level data only. It identifies no shopper, and there is no column anywhere in its database for a customer id, an e-mail address, an order id or a hash of either.
A shop domain such as demo.myshopify.com is a business identifier. Where a merchant is a sole trader (eenmanszaak), data about their shop can relate to them as a natural person, so the app treats everything below as if it were personal data: one lawful basis per purpose, one retention term per record, and an erasure that actually erases.
3.1 The install record — table shops
| Field | What it is | Why it is stored |
|---|---|---|
shop_domain | The shop's .myshopify.com domain | Identifies the shop whose data this is |
installed_at | When the app was first installed | Support, and the start of the relationship |
updated_at | When the record was last written | Support; a re-install issues a new token |
currency | The shop's currency code | A price history is meaningless without it |
scopes | The access scopes Shopify granted | So the app knows what it may ask Shopify for |
access_token_sealed | The Shopify access token, encrypted | Calling Shopify on the shop's behalf |
The token is sealed with AES-256-GCM under a key derived from the app's own API secret, which lives in the Worker's secret store and not in the database. A copy of the database is therefore not a set of live credentials for anybody's shop.
The app asks Shopify for currencyCode and nothing else. Shopify's shop resource also carries email, shopOwnerName, phone and an address. None of them is requested, so none of them can be stored by accident.
The app holds one access scope: read_products. It reads product prices, which is what an Omnibus prior price is computed from. It asks for no scope that reaches customers or orders, so there is no version of this app that could read them.
3.2 The notice history — table notice_changes
| Field | What it is |
|---|---|
change_id | An id derived from the event that caused the change |
recorded_at | When the change was recorded |
shop_domain | The shop |
notice | Which notice this is about |
active | Whether it was switched on or off |
source | What caused the change |
This is the evidence log: which EU information notices a shop had active on its storefront, and when that changed. It is append-only and shop-level, and no shopper appears in it.
3.3 The price history — table price_points
| Field | What it is |
|---|---|
price_point_id | An id derived from the event that carried the price |
observed_at | When the price was observed |
shop_domain | The shop |
variant_id | A product variant — a product, never a person |
currency | The currency the price is in |
amount_cents | The price in integer minor units |
source | Which event carried it |
This is product data. It exists because the Omnibus prior-price rule (Directive (EU) 2019/2161 art. 6a) asks what the lowest price was in the 30 days before a reduction, and that is answerable only from a record of what the price was.
3.4 The delivery log — table webhook_deliveries
| Field | What it is |
|---|---|
webhook_id | Shopify's delivery id |
received_at | When it arrived |
topic | Which webhook topic it was |
shop_domain | The shop |
outcome | What the app did with it: handled or ignored |
order_count | How many orders a data request concerned — a number, never an order |
note | What the app did, in one line |
Every webhook Shopify sends is recorded here, including the three mandatory privacy topics. This is the record that an erasure request arrived and was carried out.
The app subscribes to five topics and no others: customers/data_request, customers/redact and shop/redact, which Shopify requires of every app; products/update, which carries the price changes the Omnibus history is made of; and app/uninstalled, which is how the app knows to delete a shop's credential the moment it stops being valid.
4. What reaches the app and is not stored
- Webhook payload bodies. A
customers/data_requestorcustomers/redactpayload names a shopper. The app verifies the delivery, records the six fields above and stores no part of the payload; for a data request it records the number of orders concerned and not the orders. logged_in_customer_id. Shopify adds this parameter to an app-proxy request when a shopper is logged in. It travels through signature verification and no further: no branch reads it, nothing is written, and a test asserts every table is unchanged after a run of proxy requests.- The shopper's request itself. The storefront badge asks the Worker for one variant's prior price. The answer depends on the shop and the variant and on nothing about the visitor.
5. Why the app stores it, and under which lawful basis
| Purpose | Data | Lawful basis (GDPR art. 6) |
|---|---|---|
| Running the app for the merchant who installed it | The install record | Performance of a contract, art. 6(1)(b) |
| Keeping the evidence log the merchant asked for | The notice history | Performance of a contract, art. 6(1)(b) |
| Computing an Omnibus prior price | The price history | Performance of a contract, art. 6(1)(b) |
| Showing that a privacy webhook arrived and was carried out | The delivery log | Legal obligation, art. 6(1)(c), and Shopify's own platform requirement |
The app does no profiling, no automated decision-making with legal effect, no advertising and no analytics of any kind. It sets no cookie: the app's own page and the storefront badge store nothing in a visitor's browser.
6. Who else sees it
| Who | What for | Where |
|---|---|---|
| Cloudflare | Hosting: the Worker that runs the app and the D1 database that stores the tables in §3 | EU jurisdiction |
That is the whole list. The app makes no other outbound call: no e-mail provider, no analytics service, no AI API and no payment processor is involved in running it. Payments for a paid plan are handled by Shopify through its Billing API, so no payment data reaches Kaderlab at all.
Shopify is the platform the merchant already has their own agreement with; this app receives data from Shopify because the merchant installed it.
The processor register Kaderlab keeps under GDPR art. 30 lives in the holding repository at docs/legal/processor-register.md, and a processor is added to it in the same change that starts using them.
7. How long it is kept
- On uninstall, Shopify revokes the access token and sends
app/uninstalled. The app deletes the install record, with its sealed token, on that delivery — within seconds rather than waiting two days. - On
shop/redact, which Shopify sends about 48 hours after an uninstall, the app deletes the shop's notice history and price history as well, and the note it writes says how many rows went from each table. - The delivery log stays. It holds no configuration and identifies no shopper, and it is the record that the erasure happened at all.
- A merchant who wants their data erased sooner can write to support@kaderlab.com.
8. Your rights
A merchant — or a person whose data is in the app because their shop is a sole trader — may ask for access, correction, erasure, restriction or a copy of their data, and may object to processing. Write to support@kaderlab.com. An answer follows within 30 days.
A complaint can be made to the Dutch data protection authority, the Autoriteit Persoonsgegevens.
9. Security
- The access token is encrypted before it reaches the database and is never written to a log, an error message or a response body.
- Every webhook delivery is verified against Shopify's HMAC signature before its body is parsed, and every app-proxy request is verified before any parameter is read.
- The Worker answers on a closed list of paths. There is no admin route, no debug endpoint and no route that reports what is deployed.
10. What this app does not do
It gives a merchant structure and a record. It does not tell them, and cannot tell them, whether their shop meets an EU information duty: that is for a qualified professional to judge. Nothing in the app issues a verdict on a duty, and nothing in this document should be read as one.
11. Changes to this policy
A change is published on the same page with a new version number. A change that alters what is stored, why, or who sees it arrives in the same change as the code that causes it.