Privacy Policy
Last updated: 2026-08-06 · Version: 2026-08-06
Status: DRAFT. Not legally reviewed. This document describes accurately what the KiriChess codebase does with data, as of the version above. It has not been reviewed by a lawyer, no data processing agreement has been signed with any sub-processor, and KiriChess is not deployed. See docs/CLAIMS.md in the project repository.
1. Who runs this
[CONTROLLER NAME AND CONTACT ADDRESS: TO BE COMPLETED BEFORE LAUNCH]
This section is intentionally left blank rather than filled with a placeholder company. KiriChess has no published legal entity, postal address or contact email yet, and inventing one here would be worse than leaving it visibly incomplete.
2. What is collected
- Account: email, a hashed password (ASP.NET Core Identity’s default hasher: PBKDF2 with HMAC-SHA256; the plaintext password is never stored or logged), display name and its normalized form used only to enforce uniqueness and block impersonation, account creation time, email-confirmation state, and lockout/failed-login counters.
- Consent (this phase) : the timestamp of accepting the Terms and Privacy Policy, the policy version accepted, and the timestamp of the age declaration made at signup.
- Optional Google sign-in : only the provider’s opaque account key. No Google password, access token or refresh token is ever stored, and this system never calls a Google API on your behalf.
- Gameplay: every game’s full move list (each ply: the move, clock state, and server-measured think time), the exact rule configuration the game was played under, both players’ account ids, start/end timestamps, and the resulting Glicko-2 rating and rating history.
- Moderation: reports you file against other players, reports other players file against you, and any sanction issued against your account. A moderator-only note exists on both reports and sanctions; it is never shown to you and never exported.
- Sessions: refresh tokens, stored as a SHA-256 hash, never the raw token, plus issue time, expiry time and revocation time.
- Logs: your account id (not your email) is attached to the log lines produced while you are signed in, so an error can be traced to an account without a human reading email addresses out of logs.
- Rate-limiting: your IP address is used as an in-memory or Redis counter key to throttle requests. It is never written to a database table and is not retained beyond the counting window.
Nothing above includes a date of birth. See §9.
3. Why (lawful basis, GDPR Art. 6)
- Contract (Art. 6(1)(b)): your account, display name, games, ratings and sessions exist because running a chess account and its games is the service you asked for.
- Legitimate interest (Art. 6(1)(f)): reports, sanctions, the user-id log scope, and IP-based rate limiting exist to prevent abuse, cheating and denial-of-service against other players and the service itself.
- Consent (Art. 6(1)(a)): nothing is currently collected on the basis of consent alone. Terms/Privacy acceptance and the age declaration are a condition of using the service, not a separable consent to an optional processing activity.
4. Who it is shared with
| Party | Purpose | Status in code |
|---|---|---|
| Resend | Transactional email (confirmation, password reset) | Wired, but fails closed with no API key configured: no email has ever been sent by this system, to anyone. |
| Sentry | Error monitoring | Wired in both frontend and backend, with sendDefaultPii: false, errors only, no tracing, profiling or session replay. |
| Optional OAuth sign-in | Wired, but inactive without a configured client ID and secret; none exist in any deployed environment today. | |
| Fly.io / Neon / Cloudflare | Hosting, database and CDN | Chosen but not deployed: nothing runs on them yet. |
No sub-processor above has a signed data processing agreement in place. This is stated for every party regardless of whether it is currently active, not omitted because it happens to be inactive.
5. How long it is kept
Some of this is deleted automatically. Most of it is not, and the parts that are kept indefinitely are listed here rather than left to be discovered.
| What | Kept for | Why |
|---|---|---|
Refresh tokens (RefreshTokens) | Until 30 days after the token's own expiry, so at most about 60 days from issue | A rotated token’s row is what lets the server tell a replayed stolen token from an unknown one. Deleting it as soon as it is rotated would silently switch off that detection. |
Sign-in exchange codes (ExternalLoginCodes) | Until 1 day after expiry: the codes themselves live 60 seconds | Nothing is learned from a spent code, so it is kept only long enough to outlast clock skew. |
Your account and consent record (AspNetUsers) | For as long as the account exists | It is the account. It is anonymised when you ask (§6). |
Your games and their move lists (Games) | Indefinitely | A game is a two-party record : deleting it would destroy your opponent’s copy of a game they played. This is the same reasoning that governs erasure (§6). |
Ratings and rating history (Ratings, RatingHistories) | Indefinitely | Every rating either player holds is computed from these; removing one player's history invalidates the other's rating. |
Reports (Reports) | Indefinitely | Retained under Art. 17(3)(e), for the establishment and exercise of legal claims. |
Sanctions (UserSanctions) | Indefinitely | Same basis. A ban that could be erased by deleting the account it was issued against would not be a ban. |
| Rate-limiting counters | The counting window only | They live in memory or in Redis with an expiry and are never written to a database table. |
| Server logs | Whatever the hosting platform keeps | They carry your account id, never your email address (§2). |
The two automatic deletions above are performed by a job that runs once a day. Everything else on this list is removed only when you delete your account, and only to the extent §6 describes.
Inactive accounts are not deleted automatically. An account that has never been used still holds an email address, and the storage-limitation principle points at exactly that case. This system reports such accounts to a moderator for a human decision, and does not erase them on a timer: because doing so requires being able to warn you first by email, and no email has ever been delivered by this system to anyone (§4). If that changes, this section changes with it.
6. Erasure: what “delete my account” actually does
Deleting your account does not remove your row from the database, because a chess game is a two-party record: your opponent’s copy of a game you played, and every rating computed from it, would otherwise be destroyed along with your identity. Instead, deletion is anonymisation and tombstoning.
Cascade-deleted (removed entirely, because it belongs to your account alone): refresh tokens and external-login codes, your rating rows, and your Identity logins, claims, tokens and role assignments.
Scrubbed on the surviving account row : your email, password hash, phone number and every other identifying credential field are cleared; your display name becomes “Deleted account”; your security stamp is rotated so no existing session survives.
Retained, still pointing at the now-anonymised row: your games, your rating history, reports you were involved in, and sanctions issued against you: because games and rating history are also the record of the people you played against, and reports/sanctions are retained under Art. 17(3)(e) for the establishment and exercise of legal claims, specifically so a ban cannot be erased by deleting the account it was issued against and registering again.
Deletion is immediate and irreversible. There is no undo window. If you have a game in progress, you must finish or resign it first.
7. Export (GDPR Art. 20)
GET /api/account/export returns a JSON file of your data as an authenticated, synchronous download: there is no emailed link and no background job, because this system’s transactional email is not currently capable of delivering one reliably (see §4). The export excludes:
- Any other player’s email address or account id: games list opponents by display name only, the same name already public on the leaderboards and every game page.
- The identity of anyone who reported you: a report filed against you is exported without the reporter’s id or name.
- Every moderator note, on both reports and sanctions.
- Any raw session credential: session entries carry only their timestamps, never the token itself.
Very large accounts are capped (5,000 games, 10,000 rating-history rows) and the export says, per collection, whether the cap was hit.
8. Your rights
- Access: the export in §7 is the access mechanism.
- Rectification: your display name can be changed by you (subject to the rename cooldown and naming policy) or by a moderator.
- Erasure: §6.
- Portability: §7.
- Objection: because most processing here rests on contract or legitimate interest rather than consent, objection in practice means using the erasure right in §6.
- Complaint: you may lodge a complaint with your local data-protection supervisory authority.
9. Minimum age
You must be at least 16 years old to use KiriChess. This single global threshold is chosen because GDPR Art. 8 sets the age of digital consent between 13 and 16 depending on EU member state, and 16 satisfies the strictest of them while also clearing the US COPPA threshold of 13 outright: the only choice that does not require detecting which country you are in.
The age check is a self-declared checkbox at signup, recorded as a timestamp. No date of birth is collected or stored anywhere in this system. A self-declared date of birth would not provide any more real assurance than a checkbox, and it would create a new piece of sensitive personal data that then needs its own retention, export and erasure handling for no actual gain in enforcement.
10. Security
Passwords are never stored in plaintext: only a PBKDF2/HMAC- SHA256 hash (ASP.NET Core Identity’s default). Refresh tokens and one-time external-login codes are stored as SHA-256 hashes, not as their raw usable form. Traffic is expected to run over TLS in any real deployment. Requests are rate-limited by IP to slow abuse. None of this has been externally audited, certified, or subjected to a bug bounty: do not read any of the above as a compliance certification, because it is not one.
11. Changes to this policy
This document is versioned by the “Last updated” / “Version” date at the top. A future version that changes what is collected or how it is used will change that date; the version an account most recently agreed to is recorded on that account.
See also the Terms of Service.