Skip to contents

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

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 APIs

Mosaic 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.

  1. 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.

  2. 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.

  3. 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.

  4. 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).

  5. 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).

Cookies & similar

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