Skip to content

Trust

Security

What protects your account and your photographs, described as it is actually built.

Last updated 21 July 2026

Your files

  • Every storage bucket is private. There is no public URL for any file you upload or generate.
  • Images are reached only through signed links that expire within the hour, minted per request and checked against the account that asked for them.
  • Uploads go straight from your browser to storage through a one-time signed ticket. The path is allocated by our server from your account id, never taken from the request — so an upload cannot be aimed at someone else’s folder.
  • Uploaded files are verified against their real binary signature before anything references them. A file claiming to be a JPEG that is not one is deleted rather than stored.

Your data

  • Row-level security is enabled on every table. A query issued with your session can only return rows belonging to you — enforced by the database, not by application code that could forget a filter.
  • Credits are an append-only ledger. Nothing updates or deletes an entry; corrections are written as new compensating entries, so the history behind your balance is always complete.
  • Clients cannot write to anything billable. Credit entries, job records and generated images are all written server-side only.
  • Our schema verifier tests that these denials actually happen, rather than that the policies merely exist.

Your session

  • Sessions are HTTP-only cookies. Tokens are verified against the auth server on every protected request, not merely decoded.
  • Sign-in supports Google, a password, or a one-time email link.
  • Sign-in failures return one message whether or not the account exists, so the form cannot be used to discover who has an account.
  • Post-sign-in redirects are validated, so a crafted link cannot bounce you to another site while appearing to be us.

Payments

Card details never reach our servers. Checkout is hosted by the payment processor, and we store only a transaction reference. Payment webhooks are signature-verified before they are allowed to change anything — an unverified event cannot grant a credit.

The generation provider

  • API credentials live only on the server and are never exposed to a browser or mobile bundle. That boundary is enforced by a lint rule, not by convention.
  • Completion callbacks are verified with ED25519 signatures against the provider’s published keys, with a five-minute replay window. An unsigned or stale callback is rejected before it touches the database.
  • A reconciliation sweep checks jobs directly with the provider, so a lost callback cannot strand your work or your credits.

Reporting a vulnerability

If you find a security issue, please tell us before telling anyone else. Write to us via our contact page with enough detail to reproduce it.

We will acknowledge within two working days, keep you updated while we fix it, and credit you when it is resolved if you would like us to. We will not pursue legal action against anyone acting in good faith who reports privately and does not access data beyond what is needed to demonstrate the issue.