Overview
Charlie is built on security-first principles: no customer PII, no payment data, minimal Shopify API permissions, and full data residency within the Shopify and Cloudflare ecosystem.Data governance
What Charlie stores
Charlie stores only operational configuration in its own database (Cloudflare D1 — SQLite). The complete database schema contains ten tables, none of which hold customer PII:What Charlie writes to Shopify
Charlie computes and writes back operational values to Shopify metafields. All values are merchant configuration or computed inventory data — no customer data is involved. Variant metafields
Product metafields
Location metafields
What Charlie never touches
The following data stays exclusively within Shopify and is never accessed, processed, or stored by Charlie:- Customer PII (names, emails, addresses, phone numbers)
- Payment and billing information
- Order content and transaction history
- Customer purchase history
Data ownership and portability
Shopify API permissions
Charlie requests only the scopes required for omnichannel fulfillment operations. No customer data scope is requested or used.Security controls
Authentication and session management
- All admin routes enforce
shopify.authenticate.admin(request)before any processing — unauthenticated requests are rejected immediately - Sessions stored in Cloudflare D1 using Shopify’s official session storage adapter
direct_api_mode = "online"— no long-lived offline tokens- Access tokens stored server-side only, never exposed to client-side code
Multi-tenancy isolation
Every database query is scoped byshop domain at the ORM layer.
No query executes without an explicit WHERE shop = ? filter
derived from the authenticated Shopify session. This is enforced
in code on every data access function — not by convention alone.
Webhook security
HTTP security headers
Applied globally to all requests via HonosecureHeaders() middleware:
Content-Security-Policy and X-Frame-Options are intentionally
omitted. Charlie runs as a Shopify embedded app inside an iframe —
Shopify manages these restrictions at the platform level.Rate limiting
Charlie implements a token-bucket rate limiter for all outbound Shopify API calls:- Max 20 requests/second toward Shopify API
- Max 10 concurrent requests per worker instance
- Queue-based backpressure — requests wait rather than fail under load
Encryption
Error monitoring
Sentry is used for operational error monitoring. Error payloads contain stack traces and request context only — no customer PII, no access tokens, no session content. Sentry is disabled in development environments.GDPR compliance
Charlie implements all three mandatory Shopify GDPR compliance webhooks:Shop redact (shop/redact)
Triggered when a merchant uninstalls and requests data deletion.
Charlie deletes all shop-specific data atomically across all database tables.
Customer data request (customers/data_request)
Charlie acknowledges this webhook and returns no data — by design.
The app stores no personal customer data to return. This is
documented explicitly in the codebase:
This app does NOT store any personal customer data.
We only store shop-level configuration (locations, safety stock
rules, etc.). No customer PII, order details, or personal
identifiers are persisted. If this app ever stores customer data
in the future, this service must be updated.
Customer redact (customers/redact)
No-op by design — Charlie stores no customer-level data to redact.
Infrastructure and sub-processors
Charlie does not currently hold SOC2 certification.
All compute and storage infrastructure runs on Cloudflare (SOC2 Type II certified).