Security

You approve every write.
Transparent by default.

Legible accesses exactly the data it needs to score your catalog, measure the sales impact of your optimizations, and apply approved changes — and nothing else. No customer data. The full audit runs without write access; write access is an optional scope you grant only when you first Apply a change. We read order data only in a strictly minimized form — quantities, products, and totals — to show before/after sales, and we keep only non-personal sales aggregates from it. Every write to your Shopify store happens only on your explicit Apply click on a specific suggestion, and every change is independently undoable for 30 days. This page explains what we read, what we write, where the data goes, how long we keep it, and what happens when you leave.

Access model

Read-only by default. You approve every write.

Legible installs with the minimum read scopes required to run the six-pillar audit. Write access is a separate, optional scope you grant only when you choose to publish a change. The complete list:

read_products read_locales read_translations read_orders write_products (optional)

read_products gives us access to product titles, descriptions, variants, metafields, and image URLs — the data the six core pillars score. read_locales and read_translations give us access to your enabled markets and translated product strings for the multilingual audit. read_orders is used only to measure the before/after sales impact of your catalog optimizations, and we read it in a strictly data-minimized way: only an order's identifier, date, line-item quantity and product, and total amount — never a customer name, email, phone, or address. The raw order is discarded immediately; we keep only non-personal per-product daily sales aggregates (units and revenue), which carry no customer linkage. These four read scopes are requested at install.

write_products is an optional scope. It is not requested at install — Shopify prompts you to grant it the first time you click Apply on a specific suggestion. It is used only to publish merchant-approved product content: a description rewrite (via productUpdate) or a structured product metafield value (via metafieldsSet). No other product field, and no non-product resource, is ever written, and every applied change is independently undoable for 30 days. A server-side scope guard verifies the live granted scopes before every write and refuses the operation if write access has not been granted. You can run the full audit forever without ever granting write access.

Customer data, payment data, fulfilment data, and staff data are never accessed — Legible does not request the read_customers, read_payment_mandate, read_files, or other scopes. Order data is read only in the data-minimized form described above (no customer fields, non-personal aggregates only) and never to build any customer profile.

Data flow

What data leaves Shopify.

Some product data is sent to third-party AI services to produce scores. Here is the complete list of what moves and where it goes:

Product title + description text — sent to Anthropic Claude Haiku for description quality scoring. Haiku returns a numeric score and reasoning. Text is not used to train Anthropic models (API usage, not consumer product).
Product titles, descriptions, and tags — sent to Voyage AI for embedding generation (voyage-3-lite model). Embeddings are used for duplicate detection. We have opted out of Voyage AI's data retention and model-training program (the Section 3(iii) opt-out): going forward, Voyage AI retains zero data from our submissions and does not use it to train models. Only non-personal product text is ever sent — never customer or order data.
Product image URLs — image metadata (URL, alt text string) is read from Shopify. Image files are not downloaded or stored by Legible. URLs are sent to Claude Haiku for alt text quality assessment only when alt text is present.
Customer data — never. Legible does not request, read, or process any customer records, email addresses, phone numbers, or shipping addresses. The read_customers scope is not requested.
Order data — never sent to third parties; read in minimized form only. Under read_orders, Legible reads only an order's identifier, date, line-item quantity and product, and total — never payment methods, customer details, or addresses — and keeps only non-personal per-product daily sales aggregates to show before/after sales impact. Order data is processed on Legible's own servers and is never sent to any AI sub-processor.
AI-generated changes — only when you click Apply. When you approve a specific suggestion by clicking Apply, the change is written back to your Shopify product: a description rewrite via the productUpdate mutation, or a structured product metafield value via the metafieldsSet mutation. This requires the optional write_products scope, which Shopify asks you to grant the first time you Apply. The write happens server-side from Fly.io Paris to Shopify. Each applied write is logged and independently undoable for 30 days. No other product field, and no non-product resource, is ever written.

Infrastructure

Where your data lives.

The Legible application runs on Fly.io, deployed to the Paris (cdg) region. Catalog data — product scores, metafield coverage, duplicate clusters, and audit history — is stored in a SQLite database on an encrypted persistent volume attached to the Fly.io application. The encryption key is managed by Fly.io's volume encryption layer.

All traffic between your browser, the Legible app, and Shopify's API is encrypted with TLS 1.3. Connections that negotiate below TLS 1.2 are rejected. There is no unencrypted HTTP access to any Legible endpoint.

The marketing site (this page) is served from Vercel's edge network via Cloudflare. No catalog data is processed or stored on the marketing site infrastructure.

Data retention

How long we keep your data.

Catalog data — product scores, embeddings, audit history, metafield coverage snapshots, and the non-personal per-product sales aggregates derived from order data — is retained for the duration of your active subscription plus 30 days after uninstall. The 30-day window lets you reinstall without losing your history. After 30 days, all of this data for your shop is permanently deleted from Legible's database.

Legible honors all three GDPR mandatory webhooks from Shopify:

  • customers/data_request — Legible stores no customer PII. We respond with an empty dataset within 30 days.
  • customers/redact — No customer records to redact. Confirmed immediately.
  • shop/redact — All catalog data for the shop is permanently deleted within 30 days of the webhook being received, per Section 8 of the Privacy Policy and Shopify API Terms §6.2.3.

Session tokens and OAuth credentials are deleted immediately upon uninstall. No re-authentication is possible after uninstall without going through the full install flow again.

Offboarding

What happens when you uninstall.

When you uninstall Legible from the Shopify admin, the following happens in sequence:

  1. Your OAuth session token is revoked and deleted immediately.
  2. All active sync jobs for your store are cancelled.
  3. Your catalog data remains accessible in read-only mode for 30 days so you can export your last report.
  4. After 30 days, all catalog data — product scores, embeddings, duplicate clusters, audit history — is permanently deleted.
  5. Billing stops immediately per Shopify's app billing policy. Refunds for unused days are processed per Shopify's standard policy.

There is no hidden retention. Once the 30-day window closes, your data is gone and cannot be recovered.

Sub-processors

Every service that touches your data.

The following third-party services process data on behalf of Legible. This list is complete as of the audit date below.

Service Purpose Region Security page
Anthropic (Claude Haiku 4.5) AI description scoring + AI-generated description rewrites and product metafield suggestions (each gated by our hallucination scan + prompt-injection guard before persistence). No training on API inputs per Anthropic's DPA. US (API) anthropic.com/security
Voyage AI (voyage-3-lite) Product embedding generation for duplicate detection. We have opted out of Voyage AI's data retention and model-training program (the Section 3(iii) opt-out); going forward, Voyage AI retains zero data from our submissions and does not train on it. Standard Contractual Clauses under Voyage AI's Data Processing Addendum cover the EU/UK-to-US transfer. US (API) voyageai.com/security
Fly.io Application hosting and persistent storage (catalog data) Paris, EU (cdg) fly.io/docs/security
Cloudflare R2 Encrypted, point-in-time database backups via Litestream replication (catalog data) EU (R2 jurisdiction eu) cloudflare.com/trust-hub
Vercel Marketing site hosting (no catalog data processed) Edge / global vercel.com/security
Cloudflare DNS, CDN, and Web Analytics (no catalog data) Edge / global cloudflare.com/trust-hub

Last audited 2026-05-19. Sub-processor list updated when services are added or removed. Material changes notified via the Legible changelog.

Write safety

How writes are guarded.

The optional write_products scope is used only to publish merchant-approved product content — a description rewrite or a structured product metafield value — that you have explicitly approved by clicking Apply on a specific suggestion. No other product field, and no non-product resource, is ever written. Every write must pass the four safety rails below before it lands in your store.

  1. Hallucination scan. A regex-based scan rejects rewrites that introduce unsupported regulatory claims (e.g. organic, FDA, certified, ISO, gluten-free, cruelty-free, vegan, fair-trade, hypoallergenic, clinically-proven, cures/treats/prevents), numeric claims with units (currency, dimensions, weight, capacity, percentages), or brand names not present in the source description. A rewrite that introduces any unsupported claim is rejected before persistence — you never see the bad suggestion in your dashboard.
  2. Prompt-injection guard. Product descriptions can contain adversarial instructions ("ignore previous instructions and..."). A versioned prompt-injection test battery and system-prompt hardening defend against these attempts. Any rewrite that contains hallucinated regulatory, numeric, or brand claims resulting from a successful injection is caught by the hallucination scan and rejected before persistence.
  3. Per-plan daily cap. A rolling 24-hour window caps successful writes per shop: Starter 500, Pro 2,000, Business 10,000. Undoing a previous write does not consume the cap. The cap is enforced server-side before the Shopify mutation fires, so a runaway client cannot bypass it.
  4. 30-day undo with conflict guard. Every applied write logs a row to an audit table that allows you to undo for 30 days. Before performing an undo, Legible reads the current value of the affected field from Shopify and compares it to what we wrote. If they differ — meaning another tool or you edited that field in Shopify between our apply and your undo — we refuse to silently overwrite the foreign edit and present a three-way diff so you can resolve manually.

Every audit row is tenant-isolated by Shopify shop ID. A forged identifier from a client cannot retrieve another shop's records.

Disclosure

Vulnerability disclosure.

If you discover a security vulnerability in Legible — the app, the marketing site, or any related infrastructure — please report it by email to hamza@trylegible.com with the subject line "Security disclosure." We aim to acknowledge all reports within 48 hours and resolve confirmed vulnerabilities within 14 days of triage.

There is no formal bug bounty program yet. Researchers who report confirmed vulnerabilities responsibly are credited in the Legible changelog by name (or pseudonym, if preferred). We ask that you do not publicly disclose findings until we've had a reasonable window to patch.

We do not pursue legal action against researchers who discover and report vulnerabilities in good faith, follow responsible disclosure practices, and do not access or exfiltrate real merchant data.