GhostCoach is a desktop application for practising aim and utility placement in games. This policy covers the application, the community catalogue at community.ghostcoach.pro, and the signalling relay at relay.ghostcoach.pro.
Last updated 29 August 2026.
Who is responsible for your data
Jordan Eaks, trading as GhostCoach
11807 Allisonville Rd. # 550
Fishers, IN 46038
United States
GhostCoach is run by one person as a sole proprietorship. There is no company between you and them: Jordan Eaks is the data controller personally, decides what happens to everything described here, and is who a request or a complaint reaches. "GhostCoach" is the registered name the business trades under, not a separate legal person.
The address above is a mail-receiving address rather than an office. Post sent there reaches us; there is nobody to visit.
Privacy questions and requests: privacy@ghostcoach.pro. It is read by that same person. There is no ticketing system and no privacy team, which is worth knowing because it sets the expectation correctly — a reply may take a few days, and it will come from a human who can actually do the thing you asked for.
The short version
Almost nothing about you leaves your computer, and none of it leaves by default. There is no analytics, no telemetry and no crash reporting in this application — not disabled by a setting, absent from the source. Your clips, your training history, your settings and your friends list are files on your own disk.
Three things can be sent, and each one requires you to act first:
- An email address, if you choose to make an account.
- A bug report, if you write one and press send. You are shown the exact diagnostics block before it goes, and you choose whether to attach it.
- The clips you download, which necessarily tells our server which clips were downloaded.
There is a fourth that is worth naming separately because it is not storage: during a live coaching session your computer talks directly to the other person's, and when a direct connection is impossible the audio and video pass through a relay. See Live sessions.
What never leaves your machine
Held in a database in your user profile, and never transmitted:
- Every routine, version, marker, checkpoint and drawing you create.
- Every attempt, score and run region — what you practised, how often, and how you did.
- Your imported and recorded video, and the frames extracted from it.
- Your overlay preferences, hotkeys and display profiles. *(These are sent only if you turn on settings sync by making an account — see below — and even then the display profile is deliberately excluded.)*
- Your friends list. The application derives a room code from a shared secret; no server is told who your friends are, and the relay has no database in which it could record them.
- The application's log files. These are written by around a hundred call sites with no scrubbing, and are never sent anywhere. *Settings → Report a problem* has a button that opens the folder so you can look at one and attach it deliberately if we ask.
- Whether your last membership check said you were a member, and when. Loading your own footage needs a membership, and that check has to work on a train, so the answer is remembered here rather than asked for every time. It is one boolean and one timestamp; it never travels, and being offline cannot turn it into a yes it was not already.
We cannot produce any of this on request, because we do not have it.
What is stored, table by table
Everything the servers hold, without exception. If a row is not here it does not exist; tests/unit/privacy.test.ts fails if the catalogue schema grows a table this table does not name.
| Store | What is in it | Why | Lawful basis | Kept |
|---|---|---|---|---|
account |
Your email address, when the account was created, when it was last used, and whether you opted in to marketing | To have an account at all, and to email you a sign-in code | Contract | Until you delete the account |
account_setting |
Your synced overlay preferences and hotkeys, as one opaque blob | To carry settings between your machines | Contract | Until you delete the account |
auth_code |
Your email address and a salted hash of the current sign-in code | To check the code you type | Contract | 10 minutes, then deleted by an hourly sweep — including codes that were never used |
session |
A salted hash of your session token and its dates. Never the token | To keep you signed in | Contract | 90 days from last use, then deleted by the same sweep |
clip_like |
Which clips you liked, and when | To rank the catalogue, and to show your own likes back to you | Contract | Until you unlike, or delete the account |
clip |
A clip's title, description, game, dimensions, hash and the credit its uploader chose | To run a catalogue | Legitimate interests | While published |
clip_tag, tag, game |
Labels on clips | To sort a catalogue | Legitimate interests | While published |
clip_report |
The reason someone flagged a clip, any detail they wrote, and a salted hash of their IP address | To take down stolen or abusive footage, and to stop one person flooding the queue | Legitimate interests | The report is kept for moderation; the hash is erased after 30 days |
bug_report |
What you typed, and the diagnostics block if you ticked the box. Also the app version and a salted hash of your IP address | To fix the thing you reported | Legitimate interests | Kept while the bug is open and afterwards as a record of the fix; the hash is erased after 30 days |
subscription |
Your Stripe customer and subscription ids, the status of your membership, which plan, and when the period ends. No card details | To know whether you can download clips, and to let you manage your billing | Contract | Until you delete the account, which also cancels the subscription |
free_download |
Which clips you downloaded on the free plan — at most three rows, and only while you are on it | To count the three free downloads, so a re-download does not cost you a second one | Contract | Deleted the moment you subscribe, and with the account otherwise |
subscription_change |
The dates your membership changed status, and what it cost at each point. No card details, no other detail about the change | To count how many memberships start and end each month — questions about the past that current state cannot answer | Legitimate interests | Until you delete the account |
stripe_event |
The id and type of each billing event Stripe has sent us. No personal data of yours | So a redelivered event is not acted on twice | Legitimate interests | 30 days, then deleted by the hourly sweep |
promo |
Our own announcements | To show them | Legitimate interests | Until withdrawn |
Four things that are absent and would be normal elsewhere:
- There is no impression, click or view count anywhere. Not on promos, not on clips beyond a download counter the catalogue's ranking reads.
- A member's downloads are not recorded. A download increments a number on the clip; no row says who fetched it.
There is one exception and it is the free plan. Three downloads is a limit, and a limit has to be counted somewhere, so while you are on the free plan we record which clips you took — at most three rows, in free_download above. We record which rather than merely how many so that re-downloading a clip you already have costs you nothing: a counter would be more private and would take a slot from anybody who reinstalled or signed in on a second machine.
Those rows are deleted the moment you subscribe. Once there is no limit, the record is not enforcing anything — it would just be a list of what you downloaded, which is the thing this section says we do not keep.
- Nothing records what you did with a clip. Downloading one is the only event that touches a server. Whether you trained against it, how often, and how you did stays on your machine.
- The operator's console reads these tables and nothing else. Every number we look at internally — signups, memberships, revenue, bug reports — is a count over rows already listed above, held for the reasons already given. There is no separate analytics store, no event pipeline, and no way for the application to send us an event: the console has no route that accepts one, and a test fails if it grows one.
The credit on a clip
clip.uploader_name is free text an uploader chose — "a credit rather than an identity". It is not linked to an account, two people can hold the same one, and it survives account deletion by design: a creator leaving does not un-credit the clips other people are training against. If a credit is your real name and you want it changed or removed, write to privacy@ghostcoach.pro and we will, because that is a different request from deleting an account.
The diagnostics block
Only present if you ticked the box, and you are shown it in full before you send. It is: the app version, your OS name and version, whether FFmpeg and NVENC and Windows Graphics Capture were found, how many monitors you have, the status of seven pre-flight checks, and whether a session was live. It contains no machine name, no user name, no file paths, no room code and no information about who you were in a session with.
The application enforces this rather than promising it: the block that is displayed is the same object that is sent, asserted on object identity, and npm run verify:support drives the real form against a real server and checks that every stored field was on screen first.
Live sessions
A coaching session is a direct connection between two computers. Nothing about its content reaches us — we cannot see or hear it, and there is nothing to store, because we are not in the path.
To set one up, both computers connect to a relay that passes connection offers between them. That relay:
- has no database of any kind — there is no storage binding on the Worker, and the room membership it holds lives only in the memory of an open connection;
- never records room codes, in a log or anywhere else. A room code is the whole credential for a session, so it travels in a header rather than in the URL, because URLs are what infrastructure logs by default;
- logs one line when someone joins and one when they leave, containing a randomly-generated peer id and a count. Not a code, not a display name, not an address.
When a direct connection is impossible, the audio and video are relayed through Cloudflare's TURN service instead. This is normal WebRTC behaviour and it applies to a minority of connections — typically where both ends are behind restrictive network address translation. The media stays encrypted end-to-end; the relay forwards packets it cannot read. Credentials for it are minted per session and expire after four hours.
Who else handles it
| Processor | What they get | Where |
|---|---|---|
| Cloudflare | Everything in the tables above; they host the database, the object storage, the Workers and the TURN relay. Also, as any host does, the IP addresses that connect | Global edge network |
| Resend | Your email address and the sign-in code, at the moment one is sent | United States |
| Stripe | Only if you buy a membership: your email address, and whatever you enter on their payment page | United States |
Sign-in emails are plain text. There is no tracking pixel, no click-wrapped link, and no HTML — partly because a six-digit code rendered as a marketing template looks exactly like phishing, and partly because a tracking pixel in a security email is indefensible.
We never see your card. Paying and managing a membership both happen on Stripe's own pages, in your browser. A card number does not pass through this application, or through any server we run, and there is nowhere in our database it could be written even by mistake. What we store is Stripe's id for you, the status of your membership and when it renews — enough to answer "can this person download", and nothing more. Stripe is the controller of the payment data it holds, under its own privacy policy.
Where it physically is. GhostCoach is run from the United States, and both processors are US companies. If you are in the UK or the EEA, using this product means your email address is transferred to the United States. That is not a footnote to be buried: it is the practical consequence of a one-person product run from another continent, and you should know it before you make an account rather than after.
Those transfers rely on the standard contractual clauses in the processors' own data processing agreements — Cloudflare's and Resend's, not ours. We do not maintain a separate transfer mechanism, and saying we did would be a claim nobody could check.
Your rights, and where they are
You can do most of this yourself, in the application, without asking us:
- See everything we hold. Settings → Account → Download my data writes a JSON file of every row above that belongs to you and opens the folder. It is generated from the same list of tables the deletion walks, so it cannot quietly omit something that would nonetheless be deleted.
- Delete it. Settings → Account → Delete account. **If you have a membership this cancels it first**, and refuses to delete anything if the cancellation fails — being erased while still being charged is the one outcome worse than not being erased yet. This removes the rows — there is deliberately no "deleted" flag, and a test fails if one is ever added, because a record that keeps your address is not erasure. Your sessions, synced settings and likes go with it, each named explicitly rather than left to a database setting.
- Change your marketing preference. A toggle in the same place, effective immediately.
- Correct something. Your email address is the only thing we hold that could be wrong, and the fix is to delete the account and make one with the right address.
For anything else — objecting to a processing activity, asking for a portable copy in another format, or a question this document does not answer — write to privacy@ghostcoach.pro. We will answer within one month.
Everyone gets these rights, wherever they live. Not because every reader's law demands it, but because the code that provides them cannot tell where you are and there would be no point building a check to withhold them.
If you are in the UK or the EEA
The UK and EU GDPR reach us because we offer this product to people there, even though we are not established there. Your rights are the ones set out above, plus the right to object and the right to restrict processing, both of which are handled by writing to the address above.
You can complain to your own national data protection authority — the Information Commissioner's Office in the UK, or your member state's authority in the EU — and you do not have to raise it with us first. The list is at edpb.europa.eu.
We have not appointed an Article 27 representative. That is a deliberate, recorded decision rather than an oversight. Article 27 requires a non-EU controller offering goods or services into the EU to designate a representative there; the exemption for occasional, low-risk processing is arguable here — one email address, no special categories, no monitoring of behaviour — and it is genuinely arguable rather than clear. If EU sign-ups become more than incidental, this needs revisiting, and the honest answer then is to appoint one rather than to keep leaning on an argument.
If you are in the United States
There is no federal privacy regulator to complain to. You can raise a concern with the Federal Trade Commission, or with your state's Attorney General.
The California, Colorado, Connecticut, Texas and Virginia privacy laws each apply above thresholds — revenue, or numbers of consumers — that a one-person product does not meet, so they very likely do not apply to us. We are telling you what those laws would give you anyway, because it is already built:
- Know and access. Download my data.
- Delete. Delete account.
- Opt out of sale or sharing. Nothing to opt out of. **We do not sell personal information, and we do not share it for cross-context behavioural advertising.** There is no advertising identifier, no third-party pixel and no data broker anywhere in this product, and the house-ad system is built so it cannot become an ad network — see
docs/SAFETY.md. - Non-discrimination. Exercising any of this changes nothing about what the product costs you or what it does.
Marketing
If you tick the box when you create an account, we may email you news and offers.
It is a separate, unticked box with its own timestamp — consent bundled into signing up would not be consent. Signing in again never re-applies it, so a returning user cannot silently withdraw a consent they gave by not noticing a checkbox. Every marketing email has an unsubscribe link, and the toggle in Settings works whether or not you use it.
We do not sell or share this address, and there is no profiling: everyone who opts in gets the same email.
Children
GhostCoach is not directed at children, and accounts are not intended for anyone under 16. We do not knowingly collect anything from a child under 13, which is the line the US Children's Online Privacy Protection Act draws, and we hold the higher of the two bars rather than the one that happens to apply where we are.
We have no age verification, and pretending otherwise would be worse than saying so: an account is an email address and a six-digit code, and neither reveals how old anybody is. If you believe a child has made an account, write to privacy@ghostcoach.pro and it will be deleted.
Security
- There is no password, so there is nothing to leak and no reset flow to attack. Signing in means a six-digit code, valid for ten minutes, five attempts, three requests an hour.
- Codes and session tokens are stored as salted hashes with a server-held pepper. The database leaking is not by itself a way into anybody's account.
- Your session token is held on your machine using the operating system's own encryption. Where that is unavailable it is not stored at all and you are signed out when the application closes, rather than being written in the clear.
- The application's windows can load no remote content and make no network requests; every server call is made by the main process. This is enforced by a content security policy that a test checks byte for byte.
Changes
The version that applies is the one published here. Material changes will be announced in the application. Where a change affects what we hold about you, the in-app consent screen is re-versioned, which asks everyone again rather than relying on them to re-read a page.
Previous versions of the reasoning behind these decisions, including the dated record of reversing an earlier "there are no accounts" position, are in SAFETY.md.