# Data processing addendum **Between:** the merchant who installs Review Manager on their Shopify store (the **Controller**), and Ali Bazlamit, operator of Review Manager (the **Processor**). **Version 1.0, effective 4 August 2026.** This addendum forms part of the agreement between the Controller and the Processor and takes effect when the Controller installs the app. It reflects what the app actually does. If the app changes, this document changes with it, and the Controller is notified before the change takes effect. Terms such as *personal data*, *processing*, *controller*, *processor*, *data subject*, and *supervisory authority* have the meaning given in Regulation (EU) 2016/679 (the GDPR). --- ## 1. Roles The Controller determines the purposes and means of processing shopper personal data through the app. The Processor processes that data only on the Controller's documented instructions. Installing the app, configuring it, and using its features constitute those instructions. For merchant staff account data (Shopify session records), the Processor acts as a controller in its own right, because that data exists to authenticate the app to Shopify rather than to serve the merchant's own purposes. Shopify Inc. is a separate party with its own agreements with the Controller. Nothing here changes them. --- ## 2. Subject matter, duration, nature, and purpose **Subject matter.** Collecting, storing, displaying, and moderating product reviews on the Controller's storefront, and creating review request links for the Controller's own past buyers. **Duration.** For as long as the app is installed, plus the retention periods in section 6. **Nature and purpose.** Storage, retrieval, display, anonymisation, and deletion of review records. Read-only lookups against the Controller's Shopify data to check whether a reviewer is a past buyer, and to build a WhatsApp link the Controller can use to contact their own customer. **Categories of data subject.** The Controller's shoppers and past customers, and the Controller's own staff users. **Categories of personal data.** | Category | Fields | Source | |----------|--------|--------| | Reviewer-submitted | Display name, phone number, email address, review text, star rating, language | Typed by the shopper into the review form | | Review context | Shopify product ID, shop domain, submission time | Derived from the request | | Review request | Shopify order ID, order name, product ID, single use token, creation time | The Controller's Shopify orders | | Purchase index (pseudonymous) | HMAC-SHA256 hash of the buyer's phone number under a per-store random secret, Shopify product ID, Shopify order ID, fulfilment time, shop domain | Derived from `orders/fulfilled` and `orders/updated` webhooks | | Read but never stored | Shopify customer display name, customer or shipping phone number in readable form, order line item product IDs | Shopify Admin API and order webhooks, read per request or per delivery | | Merchant staff | Shopify session ID, shop domain, access token, scopes, expiry, staff user ID, first and last name, email address, locale, owner and collaborator flags | Shopify OAuth | **No special categories.** The app does not process data revealing racial or ethnic origin, political opinions, religious beliefs, trade union membership, genetic or biometric data, health data, or data about sex life or sexual orientation. It processes no criminal offence data and no payment card data. **No decisions.** There is no profiling, scoring, or automated decision making producing legal or similarly significant effects. --- ## 3. Processor obligations The Processor: 1. Processes personal data only on the Controller's documented instructions, including for international transfers, unless required otherwise by EU or member state law, in which case it informs the Controller first unless that law prohibits it. 2. Immediately informs the Controller if, in its opinion, an instruction infringes the GDPR or other data protection law. 3. Ensures that anyone authorised to process the data is bound by confidentiality. Access is currently limited to one named individual, Ali Bazlamit. 4. Implements the technical and organisational measures in section 5. 5. Engages sub-processors only under section 4. 6. Assists the Controller, taking into account the nature of processing, in responding to data subject requests under Chapter III of the GDPR. See section 7. 7. Assists the Controller with its obligations under Articles 32 to 36: security, breach notification, data protection impact assessments, and prior consultation. 8. At the Controller's choice, deletes or returns the personal data at the end of the service, and deletes existing copies unless law requires retention. See section 6. 9. Makes available the information needed to demonstrate compliance and allows audits under section 9. The Processor does not sell personal data, does not use it for its own marketing, does not use it to train machine learning models, and never combines one Controller's data with another's. Every database query in the app is scoped to a single shop domain. --- ## 4. Sub-processors The Controller gives general authorisation for the sub-processors listed below. The Processor imposes on each of them data protection obligations no less protective than those in this addendum, and remains fully liable for their performance. | Sub-processor | Purpose | Location of processing | |---------------|---------|------------------------| | DigitalOcean, LLC | Hosting the application server, its Postgres database, and its encrypted backups | Frankfurt, Germany (FRA1 region) | The following are used but process no shopper personal data: - **GitHub, Inc.** hosts the source repository and the container registry. The images contain application code only. - **Let's Encrypt (ISRG)** issues TLS certificates. It sees the domain name, not the traffic. **WhatsApp / Meta.** The app does not send anything to WhatsApp. When the Controller clicks "Send WhatsApp request", the server returns a `wa.me` link to the Controller's own browser and the Controller sends the message from their own WhatsApp account. Meta is therefore not a sub-processor of the Processor, but the Controller should account for that transfer in their own records. **Changes.** The Processor gives the Controller at least 30 days' notice by email before adding or replacing a sub-processor. The Controller may object on reasonable data protection grounds within that period, and if the objection cannot be resolved the Controller may terminate by uninstalling the app, with the deletion terms in section 6 applying. --- ## 5. Security measures (Article 32) These are the measures actually in place, not aspirations. Each is verifiable in the repository or on the host. **Encryption in transit.** All traffic is served over HTTPS. Caddy terminates TLS with certificates from Let's Encrypt and redirects HTTP to HTTPS automatically. See `Caddyfile`. **Network isolation.** Postgres publishes no port to the host or the internet. It is reachable only from the app containers over the internal `review_network` Docker bridge. `ufw` on the host allows only ports 22, 80, and 443. See `docker-compose.yml` and `DEPLOY_VPS.md`. **Host access control.** SSH is key-only: `PasswordAuthentication no` and `PermitRootLogin prohibit-password` are set in `sshd_config`. Deployments run through a dedicated CI keypair that is separate from the operator's personal key, and the droplet's access to the source repository is a read-only deploy key. Unattended security upgrades are enabled. **Encryption of backups at rest.** Nightly `pg_dump` output is gzipped and then encrypted with `age` before it is written to disk, using a public key whose private half is not kept on the droplet. Backups are written to a temporary file and only published after a size sanity check, are stored with mode 600 in a directory with mode 700, and are deleted after 14 days. Restores are testable without touching the live database. See `scripts/pg-backup.sh` and `scripts/pg-restore.sh`. **Application access control.** Storefront requests are authenticated as Shopify app proxy requests with signature verification. Admin requests are authenticated as Shopify session tokens. Review request tokens are 128 bit random values, are single use, and are bound to a specific shop and product. **Data minimisation.** The verified buyer badge is decided from a purchase index that stores no readable customer data. When an order is fulfilled and paid, the Processor records the product ID, order ID, fulfilment time, and an HMAC-SHA256 hash of the buyer's phone number under a secret unique to that store. The phone number itself is never written. Because the secret is per store, the same phone number hashes differently in every store, so the index cannot correlate a person across merchants. Where no index entry exists, because the order predates installation, the Processor falls back to a live Shopify lookup that reads only order line item product IDs and stores nothing. Customer names and phone numbers on the Requests page are read live from Shopify per request and are never written to the database. The review request table stores no customer name. The Processor treats the phone hash as personal data notwithstanding the pseudonymisation, and applies the same deletion, retention, and data subject rights to it as to readable data. **Logging and monitoring.** Every admin page view that displays shopper data writes a structured access log line containing the shop domain, the Shopify staff user ID, the route, a record count, and a timestamp. Reviewer names, phone numbers, email addresses, and review bodies are never written to any log. Phone numbers appearing in error logs are masked to the last four digits. HTTP access logs mask client IP addresses to a /24 or /32 prefix, drop Cookie and Authorization headers, and replace secret query parameter values, including review request tokens, with `REDACTED`. **Resilience.** The app deploys blue-green behind a health checked reverse proxy, so a bad release does not take the service down. Containers restart automatically. Database restore is tested by the procedure in `DEPLOY_VPS.md`. **Testing and change control.** All changes go through a CI pipeline that runs the test suite, a TypeScript typecheck, and a build before any image is published. Deployments to production are automated from the `main` branch. **Limits, stated honestly.** Data at rest in the Postgres volume is not encrypted at the database or filesystem level; the protection there is that the disk is not shared, the port is not published, and backups leaving that volume are encrypted. There is no on-call rota and no 24/7 monitoring. The Processor holds no ISO 27001, SOC 2, or equivalent certification and makes no such claim. --- ## 6. Retention and deletion Retention is enforced by code, in `app/services/retention.server.ts`, running on a schedule inside the application. It is not a manual promise. | Data | Retention | |------|-----------| | Reviews, shop settings | Kept while the app is installed. On uninstall, deleted after a 30 day grace period, so that reinstalling within 30 days preserves the store's reviews. | | Review requests (order ID, order name, token) | Deleted immediately on uninstall. | | Purchase index (hashed phone, product ID, order ID, fulfilment time) | Kept while the app is installed, then deleted on the same 30 day grace period as reviews. A row is deleted sooner if its order is cancelled, refunded, or voided. | | Merchant staff sessions | Deleted immediately on uninstall. Sessions whose access and refresh tokens have both expired are pruned automatically at least every six hours. | | Encrypted backups | 14 days, then deleted. | | Application and HTTP access logs | 90 days, then deleted. | The scheduled purge will not delete data for a shop that still has a live session, so a reinstall inside the grace period is safe. **Shopify compliance webhooks** are implemented and are honoured on receipt: - `customers/redact`: the reviewer's display name, phone number, and email address are set to null on every matching review for that shop, and that customer's rows are deleted from the purchase index. The anonymous rating and review text remain, as the Controller may lawfully keep them. - `shop/redact`: every review, review request, purchase index row, shop setting, and uninstall marker for that shop is deleted. - `customers/data_request`: matching review records are identified so the Controller can respond to the data subject. **Deletion on request.** The Controller may ask for immediate deletion instead of waiting out the grace period, by emailing ali.bazlamit@hotmail.com from the email address on the store's Shopify account. The Processor completes the deletion within 30 days and confirms in writing. **Backups.** Deleted records may persist in encrypted backups for up to 14 days after deletion, after which the backup itself is destroyed. Backups are not restored except to recover from a failure, and if a restore reintroduces deleted records the deletion is reapplied. --- ## 7. Data subject requests If a data subject contacts the Processor directly, the Processor does not respond substantively. It forwards the request to the Controller without undue delay and assists the Controller in answering it. Practical assistance available to the Controller: - **Access and portability.** Reviews for a shop are exportable from the database by shop domain and by reviewer phone number or email address. - **Erasure and anonymisation.** The Controller can trigger this themselves through Shopify's customer redaction flow, which the app honours automatically, or ask the Processor to run it. - **Rectification.** The Controller can edit or reject a review from the app admin. The Processor responds to a Controller's assistance request within 10 business days. --- ## 8. Personal data breach The Processor notifies the Controller of a personal data breach **without undue delay and in any event within 72 hours** of becoming aware of it, by email to the address on the store's Shopify account. The notification includes, so far as known at the time: the nature of the breach, the categories and approximate number of data subjects and records affected, the likely consequences, the measures taken or proposed, and a contact point. Where full information is not available within 72 hours, the Processor sends what is known and follows up in phases. The Processor also reports incidents involving Shopify protected customer data or Shopify access tokens to Shopify through the Partner Dashboard. The full incident response procedure, including containment and post-mortem, is in [`SECURITY.md`](https://reviews.alibazlamit.com/security). --- ## 9. Audit rights The Processor makes available to the Controller the information necessary to demonstrate compliance with Article 28. In practice this means: - This addendum, the [privacy policy](https://reviews.alibazlamit.com/privacy), and [`SECURITY.md`](https://reviews.alibazlamit.com/security), all kept current. - On written request, once per twelve month period, a written response to a security questionnaire, within 30 days. - On written request, evidence that a specific control is in place: the relevant source file, the `sshd_config` and `ufw` output, a backup listing showing encrypted files and their rotation, or an extract of the personal data access log for that Controller's own shop. - On written request, confirmation that a deletion has been carried out. The Controller may audit more deeply, including by an independent third party bound to confidentiality, on 30 days' written notice, no more than once per twelve month period unless a breach or a supervisory authority requires otherwise. Audits happen during business hours, must not disrupt the service, and must not put another Controller's data at risk. The Controller bears the cost of any audit it initiates, unless the audit finds a material breach of this addendum. Because the app is a single tenant deployment operated by one person, on-site inspection of shared infrastructure is limited to what DigitalOcean publishes about its own facilities. --- ## 10. International transfers All processing takes place in Frankfurt, Germany, inside the European Economic Area. There is no routine transfer of personal data outside the EEA by the Processor. If a transfer outside the EEA becomes necessary, the Processor will first put in place an appropriate safeguard under Chapter V of the GDPR, normally the European Commission's standard contractual clauses, will update this addendum, and will notify the Controller before the transfer begins. Data reaching the app originates from Shopify's own infrastructure. Transfers between Shopify and the Controller are governed by the Controller's agreement with Shopify. --- ## 11. Liability, term, and precedence This addendum applies for as long as the app is installed and, for the obligations that survive by their nature, including deletion and breach notification, until those obligations are discharged. If this addendum conflicts with any other agreement between the parties on the processing of personal data, this addendum prevails. Nothing here limits either party's obligations directly imposed by the GDPR. --- ## 12. Contact Ali Bazlamit, Processor. - Data protection and deletion requests: **ali.bazlamit@hotmail.com** - Security reports: **ali.bazlamit@hotmail.com** - Postal address available on request. The Processor is not required to appoint a data protection officer under Article 37 and has not appointed one. Requests are handled by the operator directly.