Last updated

Privacy Policy

How personal data is collected, used, and protected by this service.
This document is a placeholder and is not legal advice. Replace it with a policy reviewed by a qualified lawyer before going live. Once these documents are real, set legal.termsVersion in starter.config.ts to record who accepted which version, and bump it whenever they change materially.

1. Data collected

Describe what is collected — account details, usage data, cookies, and anything gathered by third-party scripts.

2. How data is used

Describe the purposes: providing the service, support, billing, analytics, and communication.

Describe the lawful basis for processing, if GDPR or a similar regime applies.

4. Sharing

List the processors and third parties data reaches, and why.

5. Retention

Describe how long each category of data is kept.

6. Your rights

Describe access, correction, deletion, portability, and objection rights, and how to exercise them.

7. Security

Describe the safeguards protecting personal data.

8. Contact

Provide a contact for privacy questions and, where required, a data protection officer. Write to legal@nnx0r.dev.

Appendix: what this application stores

Facts about the code as it ships, not legal advice — an inventory for whoever writes the sections above. Verify it against your own configuration, since most of it is switched on and off in starter.config.ts.

Account. Email address, display name, avatar image, role, the timestamps of email verification and terms acceptance. Held until the account is deleted, which removes them.

Sessions. One row per signed-in device holding its IP address, user agent and activity timestamps. Revoked rows and rows idle beyond 30 days are pruned daily; deleting the account deletes them outright.

Activity log. Sign-ins, credential changes and administrative actions, each with the IP address and user agent that produced it. Retention is activity.retentionDays — 90 days as shipped — after which a scheduled task deletes them.

Authentication tokens. Magic-link, password-reset and email-verification tokens are stored only as SHA-256 hashes, alongside the address they were issued for, and expire within minutes to a day. Redeeming one marks it spent immediately; the row itself is removed by the next sweep of expired tokens, or at once when the flow it belongs to clears them (a completed password reset, a confirmed email change, account deletion).

Payments (when enabled). The payment provider's customer and subscription identifiers, the plan held, and the raw webhook payloads that produced them. The card itself never reaches this application — the provider holds it.

Attribution and cookies (when marketing conversions are enabled). Landing on a page with an advertising click identifier in its URL writes it to an httpOnly _cid cookie, holding up to six identifiers for 90 days — the one place this application stores anything on the visitor's own device beyond the session cookie and the consent record. It is written only after marketing consent. When a checkout begins, those identifiers are snapshotted onto the account with the IP address, user agent and consent state of that moment, so the payment provider's later webhook can be attributed. Consent itself is remembered in the _ac and _mc cookies for 180 days.

Analytics (when enabled). Cookieless: a visitor is a daily-rotating HMAC of IP address and user agent, so the same person is a different identifier tomorrow and nothing is stored on their device. Cloudflare Analytics Engine retains data points for three months and cannot delete individual rows — worth stating plainly, because it bounds what an erasure request can reach.

Processors. Cloudflare hosts the application and stores its database, files and images. Whichever payment, email and analytics providers are enabled in starter.config.ts receive the data their function requires — the addresses mail is sent to, the identifiers a payment needs.

Rights already implemented. Settings → Profile offers a full data export (GET /api/auth/export) and account deletion. Both are self-service and need no request to a human.