Privacy policy
What we collect, why, and how long we keep it.
Plain-English version of the data practices behind Mosaic. We try to be specific — scope by scope, bucket by bucket — instead of hiding behind "we may collect…".
Effective: 2026-07-17
Jump to a section
- In one paragraph
- Who we are
- What we collect
- Google services — what we access, exactly
- Limited Use commitments (Google API Services User Data Policy)
- Subprocessors (who we share data with to run the service)
- Cookies & similar
- Where your data lives
- Retention & deletion
- How we protect your data
- Your rights
- Children's privacy
- Changes to this policy
In one paragraph
Mosaic is a catalogue-template service for teams who ship weekly. To run it, we store the account information you give us (or that Google gives us when you sign in with Google), the catalogues, templates, and assets you upload, and the export files we render for you. If you connect Google Drive, we store encrypted tokens so we can drop exports into your Drive when you ask us to. We do not sell your data, we do not use it for advertising, and we do not transfer Google user data to anyone outside the limited set of processors named below.
Who we are
The data controller for Mosaic is:
Service
Mosaic (the product formerly known as fletushka) — a catalogue-template SaaS operated by Quad Tech.
Operator
Quad Tech — the operating entity that provisions Mosaic, signs contracts, and answers privacy requests.
Contact
For any privacy question, email privacy@quadtech.dev (see the Contact section at the bottom of this page).
Where we run
Application code runs on Cloudflare's global edge network. Persistent data lives in PostgreSQL (Neon) and object storage (Cloudflare R2) — see the Subprocessors section for the full list and where each type of data is stored.
What we collect
Everything Mosaic actually stores, grouped by bucket. If a field isn't on this list, we don't store it.
Account basics
Email address, display name, hashed password (Argon2/bcrypt via Better-Auth) if you signed up with email and password, role, and the org you belong to. If you signed up with Google, see the Google services section.
Session data
Better-Auth session records (server-side, hashed token in an HttpOnly cookie), and a short-lived signed JWT (`session-jwt` cookie) that we mint for stateless authentication on oRPC requests.
Organizations
Org name, slug, members and their roles, subscription tier assignment. The "platform" org (`quad`) holds the global admin role; everything else is tenant-scoped.
Catalog content
Products (name, SKU, barcode, price, family), templates (canvas state, layers, bound fields), and assets (image metadata, byte storage in R2, SHA-256 checksums).
Imports & renders
CSV/XLSX files you upload (stored in the `catalog-imports` R2 bucket, deleted after import completes), rendered PNG outputs (stored in `catalog-renders` until you delete them or the export).
Derived assets
If background-removal is enabled (env-gated, opt-in by org), the cleaned-up variant image and a link back to the original. The provider only sees the bytes you send for that one operation.
Messaging data (if used)
If a member enables email/SMS/WhatsApp/Viber delivery for an export, the destination address or phone number, the message body, and delivery state — only for the chosen channel and only when triggered.
Audit & observability
Request logs (path, status, latency, hashed user id), structured trace events for the auth pipeline, and Worker analytics — kept for 30 days.
Google services — what we access, exactly
Google APIsMosaic uses Google in two narrow ways. Both are off by default and require your action. Read the specific section that applies before you connect either one.
Sign in with Google — only when you click "Continue with Google"
We request these OAuth scopes: `openid email profile`. Google returns a stable user identifier (`sub`), your email address, an email-verified flag, your display name, and your profile picture URL. We do not request, and do not receive, your Google password, contacts, calendar, Drive, Gmail, or any other Google product. We use this data for one purpose: create or sign you into your Mosaic account. The data lives in the same Postgres table as email/password accounts, scoped to your org.
Connect Google Drive — only when a manager/admin clicks "Connect Google Drive"
We request one OAuth scope: `https://www.googleapis.com/auth/drive.file` (also written `drive.file`). With this scope, Mosaic can only see and act on files the app itself creates in your Drive — we cannot read, list, modify, or delete files that exist outside what we wrote. The data we receive: an access token, a refresh token, and the connected Google account's email address. Tokens are encrypted at rest using AES-GCM with `TOKEN_ENCRYPTION_KEY`; they are decrypted only inside the worker that needs to call Google. Refresh tokens let us re-auth silently until you disconnect; we never store the password-equivalent `id_token` past the sign-in request.
What we do with the Drive data
One thing: when a member clicks "Export to Google Drive" on a finished export, we upload the rendered PNGs into a folder named "Mosaic" inside the connected user's Drive. We do not read, summarise, index, or transmit your Drive contents to anyone else, and we do not allow human operators to browse your Drive.
How to revoke either integration
For Sign in with Google: go to myaccount.google.com → Security → "Third-party apps with account access" → Mosaic → Remove access. Your Mosaic account survives — you can switch to email/password afterwards. For Connect Google Drive: open Settings → Integrations → Disconnect, or do it from the same Google page. We delete the stored tokens immediately on disconnect, and any exports already delivered to your Drive stay in your Drive (they're your files).
Children's & student accounts
If you signed in with a Google Workspace for Education account, Mosaic treats it like any other account but does not request or store any roster, classroom, or coursework data. Workspace admins can revoke the app's domain-wide access at any time from the admin console.
Bottom line: Google user data is used only to provide the feature you opted into, never for advertising, profiling, or any unrelated purpose. See the Limited Use section below for the exact commitments.
Google Privacy PolicyGoogle API Services User Data PolicyRevoke third-party access
Limited Use commitments (Google API Services User Data Policy)
No transfer to third parties
We do not transfer Google user data to third parties except to the subprocessors named below, and only as far as needed to provide the feature you requested.
No advertising or marketing use
We do not use Google user data for serving advertisements, including retargeting, personalised or interest-based advertising, or marketing of any kind.
No profiling or market research
We do not use Google user data to profile users, train or improve a model, conduct market research, or build audience segments.
No human reading without need and audit
Mosaic employees do not read your account content, templates, assets, or Drive exports unless you have given us written permission to debug a specific support ticket, or the access is required for legal/security reasons and is logged.
Deletion on disconnect and on request
Disconnecting either Google integration deletes the related tokens immediately. Deleting your Mosaic account deletes all associated Google-derived data (Google sub, profile fields, encrypted Drive tokens) within 30 days, subject to the Retention section below.
Subprocessors (who we share data with to run the service)
Hosting & storage
- Cloudflare
- Application runtime (Workers), edge cache, Durable Objects for realtime fan-out, R2 object storage for assets, imports, and renders, and KV for entitlements cache. Receives all HTTP traffic and all binary data we store. Region: global edge with data residency closest to the request.
- Neon (PostgreSQL)
- Managed Postgres for accounts, sessions, orgs, products, templates, audit logs. Region: configurable — default EU/US, set per-deployment.
Identity & OAuth
- Google Identity Services / Google OAuth
- Only if you use Sign in with Google or Connect Google Drive. Receives only the OAuth redirect requests and returns the data listed in the Google services section. Privacy policy: policies.google.com/privacy.
- Better-Auth (in-process)
- Authentication library that runs inside our Worker; does not transmit data to a third party.
Optional, env-gated integrations (only active when keys are configured)
- Resend (email)
- Outbound transactional email (password reset, verification). Receives recipient address and message body.
- Twilio (SMS / WhatsApp)
- Outbound SMS/WhatsApp for export notifications. Receives destination number and message body.
- BulkGate (SMS fallback)
- Alternative SMS provider for regions where Twilio is unreliable. Same data shape as Twilio.
- Viber Bot API
- Outbound Viber messages. Receives Viber user id and message body.
- remove.bg / Photoroom (background removal)
- Sends only the bytes of the image being cleaned; receives the cleaned PNG. We do not send captions, names, or metadata.
- Open Food Facts (barcode image lookup)
- Sends only the barcode digits you ask about; receives a product image URL (which we then ingest through the same SSRF-safe path as any external URL).
We use a small number of cookies and cookie-equivalent storage, all first-party. None of them are advertising cookies, none of them are shared with third parties for tracking.
Better-Auth session cookie — HttpOnly, SameSite=Lax, 7-day rolling lifetime. Set when you sign in; cleared when you sign out. The session record itself lives server-side.
`session-jwt` — HttpOnly, SameSite=Lax, 1-hour lifetime. A signed EdDSA JWT that the Worker mints so subsequent oRPC calls can verify your session by signature without a database round-trip. Cleared on sign-out.
Google OAuth state cookie — set only during the Connect flow, deleted on callback completion. Holds the CSRF state value; not used for tracking.
`darkMode` localStorage key — purely cosmetic, set by your toggle. No transmission.
`i18n_locale` cookie — set when you change language with the in-app switcher. Not used for tracking.
Where your data lives
Application runtime
Cloudflare Workers — runs at the edge closest to the request. No state.
PostgreSQL (Neon)
Configurable region per deployment. EU by default for our hosted instance; primary and read-replica in the same region.
R2 object storage
Region configured per bucket on the Cloudflare side. Assets bucket is configured EU for the hosted instance; we publish the current region in the admin footer of the dashboard.
Backups
Neon point-in-time recovery for Postgres (35 days). R2 versioning enabled for the assets and renders buckets — overwritten or deleted objects can be recovered by us within 30 days.
Retention & deletion
Active account
Kept while your account is active. You can export your data at any time from Settings → Export.
Account deletion
Soft-deletes your user record and org memberships on request, hard-deletes from Postgres within 30 days, and removes all associated binary data (assets, imports, renders) from R2 within the same window.
Disconnecting a Google integration
Tokens are deleted immediately. Derived data (your Google sub on the user record, profile picture cache) is deleted with the account.
Logs & traces
30 days, then automatically purged. Aggregated, non-personal counters may live longer (e.g. "total exports last month") but never contain user content.
Backups
Removed as the underlying backups rotate out, within 35 days for Postgres and 30 days for R2 versioning.
How we protect your data
Encryption in transit
TLS 1.2+ everywhere. Cloudflare terminates TLS at the edge; oRPC and Better-Auth are HTTPS-only.
Encryption at rest
Neon Postgres encrypts at rest by default. R2 encrypts at rest by default. OAuth refresh tokens are additionally encrypted with AES-GCM (`TOKEN_ENCRYPTION_KEY`) before write.
Access control
Permix-based role checks on every oRPC endpoint (`admin`, `manager`, `member`, scoped to your org). The platform org (`quad`) is the only one that can hold the `admin` role.
No human reads without need
Employees access user data only to respond to a support ticket you've filed, to fix a reproducible bug you've reported, or to comply with law. Every such access is logged.
Vulnerability reporting
Email security@quadtech.dev with details. We acknowledge within 2 business days and aim to ship a fix or mitigation within 30 days for confirmed issues.
Your rights
Regardless of where you live, you have at least these rights:
Access
Ask for a copy of the personal data we hold about you. Use Settings → Export, or email privacy@quadtech.dev.
Correction
Update your name, email, and most fields from Settings. For anything you can't change yourself, email us.
Deletion
Delete your account from Settings → Danger zone, or by emailing privacy@quadtech.dev. Hard-delete within 30 days.
Portability
Export bundles include your products, templates, assets, and audit log as JSON + CSV + ZIP of binaries.
Withdraw consent
Disconnect Google, disable messaging channels, or close your account at any time. Withdrawal does not affect the lawfulness of processing before withdrawal.
Complain
If you believe we've mishandled your data, email privacy@quadtech.dev. EU/UK residents may also complain to their local data-protection authority; we'll cooperate with any investigation.
Children's privacy
Mosaic is not directed at children under 16 (or under the minimum age in your country, whichever is higher). We do not knowingly collect data from children. If you believe a child has signed up, email privacy@quadtech.dev and we will delete the account within 7 days.
Changes to this policy
We update this page when our practices change. The "Last updated" date at the top of the page reflects the most recent revision. If a change is material — for example, adding a new subprocessor, or starting to use Google user data for a new purpose — we'll email every active account holder at least 14 days before the change takes effect.
Contact
For privacy questions, data requests, or to exercise any of the rights above, email us. We respond within 5 business days.
privacy@quadtech.dev