Privacy policy
Version 2026-10-28.32e04f7d ยท draft of 2026-10-28 · not yet in force
Details supplied by the owner
Scope: this policy covers personal data for which the company is the controller: visitors to our own website, account holders and their staff, billing contacts, people who contact support, and (see section 9) operators. For the customer content we process on a customer's behalf (page text, visitors to a customer's translated site) we are a processor; those terms are in DATA_PROCESSING_AGREEMENT.md, not here. This split is a working assumption verify with counsel.
1. Who we are
- Company: [LEGAL ENTITY NAME, registered address, registration number: OPEN]. Product name [OPEN: placeholder "ResilientLang"].
- Contact for privacy requests: [OPEN: mailbox]. Data protection officer: [OPEN: needed or not? verify]. EU/UK representative: [OPEN: needed? verify].
2. What we collect, why, and for how long
| Data | Where it comes from | Why (purpose) | Legal basis | Kept for | Evidence |
|---|---|---|---|---|---|
| Server access logs of our marketing site: IP address, requested page, time, browser type | automatically | security, troubleshooting | OPEN (counsel; legitimate interests is the usual candidate, verify) | OPEN: set by the web host, not by our code | src/ResilientLang.Marketing/Seo/DefaultContent.cs (says standard logs may be kept); host retention unknown |
| Marketing pages and guides: no cookies, no JavaScript, no third-party requests (except the pages with a form: sign-up, log-in and, since WP-111, /platforms/wordpress and /platforms/shopify, which set the anti-forgery cookie) | n/a | n/a | n/a | n/a | HANDOFF.md current status; Privacy.cshtml |
| Sign-up / log-in forms: e-mail address, optional name or company, anti-forgery cookie | you | create and secure your account | contract / pre-contract steps verify | account lifetime; unverified sign-ups are deleted after 7 days (see RETENTION_SCHEDULE.md and gap G11) |
; src/ResilientLang.Onboarding/ |
| Waiting list ("Notify me when it is available" on the WordPress and Shopify pages): e-mail address (stored in lower case), which platform, the exact consent wording you saw and its version, the time you signed up, the page you used; the same anti-forgery cookie as the sign-up form. No IP address and no browser details are stored. Nothing is sent yet: we do not have an e-mail provider; when we do, we will write to you once, when the platform is available | you | tell you once when the plugin or app is available | consent (an unticked checkbox you tick yourself) OPEN (counsel; a confirmation e-mail before the first message is planned once the e-mail provider exists, verify) | until you ask to be removed, or proposed: 12 months after the platform launches, whichever is first (OPEN; no automatic purge in code yet, the operator deletes entries by hand) | src/ResilientLang.Backoffice/Persistence/BackofficeDbContext.cs (table BackofficeWaitlist), |
| Password | you (chosen after e-mail verification; the sign-up form has no password field) | log-in | contract | only a PBKDF2-HMAC-SHA256 hash (600,000 iterations, self-describing, minimum 15 characters) | |
| Two-factor secret and recovery codes | you | mandatory two-factor for Owner/Admin/operator | contract / security verify | secret stored encrypted (AES-256-GCM); recovery codes stored hashed, single use | WP-32 |
| Sessions | automatic | stay signed in | strictly necessary for the service verify | server-side opaque, HMAC-hashed at rest; 30 min idle / 8 h absolute (operators 15 min / 4 h) | WP-32 |
| Sign-up abuse controls: per-IP counters (IP stored only as an HMAC hash), honeypot field, disposable-domain list | automatic | prevent abuse | legitimate interests verify | No purge exists: keys are an HMAC-SHA256 of the IP cut to 128 bits (pseudonymous only while the key is secret); rows are trimmed only when the same key is hit again; the table is not covered by tenant erasure. Retention period: OWNER INPUT | |
| Audit events of your account (who did what, when, truncated IP, no secrets) | automatic | security, accountability, your own audit log | legitimate interests / contract verify | Tenant audit log (Events): 365 days by default, adjustable 30-730 days, purged by a background worker when workers run. Not covered by that period: Identity's own audit table (rows with no tenant are never erased), the operator audit and support-grant tables, expired sessions and used tokens: no purge (DATA_MAP.md gaps 2-4); truncated IPs are IPv4 /24 and IPv6 /48 |
; WP-32 audit with truncated IPs |
| API-key records: name, scopes, prefix (first 8 characters), key hash (HMAC-SHA256 with a secret pepper), last-used time | you | authenticate API calls | contract | until the key is revoked/deleted OPEN | ; src/ResilientLang.Contracts/Interfaces.cs:132 (timestamp only; the design doc PRIVACY.md also mentions last-used IP: verify) |
| Licence records: licence key hash, plan, term, domains activated | you / billing | enforce paid plans, update server for the WordPress plugin | contract | OPEN (see lapse rules) | |
| Billing: plan, interval, subscription status, period dates, invoice mirror (number, status, amounts, period, lines, hosted links); no card data in our database. Stripe itself collects name, e-mail, card, address and tax data on its hosted pages; we keep Stripe customer and subscription ids and invoice links | payment provider | charge, invoice, entitlements | contract; legal obligation (tax records) verify | OPEN (tax record rules verify) | |
| Transactional e-mail: address, template id, delivery state; suppression list (address plus reason); outbox copy of an undelivered message | you | verification, reset, invoice, quota and failure alerts | contract / legitimate interests verify | outbox body wiped after sending; undelivered security mail expires after 30 minutes, other mail after 3 days; the recipient link and the suppression hash have no purge; the mail provider keeps its own copy of address and full body (provider retention: verify) (DATA_MAP.md gap 6, 2.2) |
|
| Support contacts and conversations | you | help you | contract / legitimate interests | OPEN (support tool not chosen) | 5.5 [planned] |
| Webhook endpoint URLs and delivery logs (status, short error, attempts; no response bodies) | you | deliver events you asked for | contract | delivery log 30 days | |
| Operational logs: structured JSON logs with API keys, bearer tokens, passwords, e-mails and secret-like query values removed | automatic | run and secure the service | legitimate interests verify | OPEN (log destination not chosen) | |
| Shopify merchants: shop domain, encrypted offline access token, granted scopes, install/uninstall times | Shopify | operate the Shopify app | contract | until uninstall plus Shopify's shop/redact window OPEN |
We do not: run analytics or advertising trackers on our marketing site, track e-mail opens or clicks (disabled on purpose,), sell personal data, or make decisions about people by automated means that have legal or similarly significant effects (no profiling features exist in the code; verify this sentence again before launch).
3. Visitors to our customers' translated websites
When a customer's site loads our loader script, a visitor's browser may request bundle files from the customer's own site and from CDN hosts. The CDN and storage providers see the visitor's IP address, user agent and Origin/Referer. The customer is the controller and we are the processor for this; the customer's own privacy notice must mention it. What the browser stores is listed exactly in COOKIES_AND_LOCAL_STORAGE.md. A cross-origin CDN receives the origin of the customer's page in Referer and Origin, never the path or query (measured in Chromium:). The loader sends no cookies (credentials: 'omit'). It never redirects by IP or Accept-Language; any language suggestion banner uses the browser language locally with no server call.
4. Customer content (summary only; the DPA governs)
Customers send us page text, URLs and glossaries so we can translate them. Text reaches machine-translation providers listed in SUBPROCESSORS.md. We tell customers that translated bundles are published on public CDNs, so personal data in source text becomes public. Known gaps: URLs are stored with query strings (G2); no filter removes personal data before text reaches a translation provider, and automatic engine selection can route text to any enabled engine in fallback order; bring-your-own provider keys are not implemented (no caller passes them), so the policy must not promise BYO yet.
5. Who receives personal data
Categories only; the maintained list is SUBPROCESSORS.md: hosting and database host; CDN and object storage; e-mail provider; payment provider (Stripe in test mode only so far; Shopify Billing for Shopify merchants); translation engines; the Shopify and WordPress platforms as the places where the product is installed; professional advisers; authorities where legally required. OPEN: which of these are processors, independent controllers or joint controllers for each data type.
6. International transfers
OPEN. The hosting location is not decided. Cloudflare, Stripe, Postmark, Google, DeepL and Anthropic may process outside the EEA/UK verify. No transfer mechanism (adequacy decision, standard contractual clauses, UK addendum, Swiss addendum) has been selected. A support person outside the EEA reading customer data in the back-office is also a transfer to assess.
7. Your rights
Access, rectification, erasure, restriction, portability, objection, withdrawal of consent, complaint to a supervisory authority (named in GDPR Arts. 15-22, 77: verify numbers and UK/US-state equivalents). How we answer is in DSAR_PROCEDURE.md. Honest status (2026-10-29): the product exports a site's translations, and an operator-run tenant erasure orchestrator with 11 module hooks exists. There is no customer-facing delete, no per-person erasure and no "export everything about me" (gap G1). Tenant erasure by default leaves invoices (minus Stripe ids/links), the audit trail, terms-acceptance proof, published bundles, signing-key tables, mail-provider copies and Stripe; Shopify tables are removed only by shop/redact. Requests are handled manually by the operator and the timings in DSAR_PROCEDURE.md are targets, not guarantees.
8. Security
Summary only; the detailed measures are in the DPA annex: TLS; passwords hashed; secrets and tokens encrypted at rest with key ids; API keys and sessions stored only as hashes; mandatory two-factor for Owner/Admin; tenant isolation tests; signed bundles; hash-chained audit log; dependency policy. Statements describe design and offline tests; nothing has run in production (G8). Breaches: BREACH_RESPONSE_PLAN.md.
9. Our own staff and support access
Support staff use a separate back-office with mandatory two-factor, role (Viewer, Support, Admin), a reason (15-500 characters) for every action, and a hash-chained operator audit log; impersonating a customer is read-only, capped at 30 minutes, and appears in the customer's own audit log (the reason is not shown to the customer). Searches are not logged verbatim (often e-mail addresses), only result counts.
10. Children
The service is for businesses. OPEN: minimum age and wording. verify local rules.
11. Changes and contact
We will update this page before adding analytics or any new use of data (the existing marketing-site page already promises this). Notice period and method for material changes: OPEN.