← skillstreak.xyz

SkillStreak — Integritetspolicy / Privacy Policy (WORKING DRAFT)

⚠️ THIS IS A NON-LEGAL WORKING DRAFT — NOT REVIEWED BY A LAWYER

Written by an AI coding agent with the project owner, grounded in what the app actually does today, so a real lawyer has something concrete to react to instead of a blank page. It is not:

Same posture as terms-of-service-DRAFT.md and code-of-conduct-DRAFT.md.

This one carries more weight than those two, for two reasons worth stating plainly:

  1. Both app stores require a publicly reachable privacy policy URL before submission. Nothing ships without one, so this draft is on the critical path in a way the others are not.
  2. This app processes children's personal data in the EU. That is the highest-sensitivity category the GDPR recognises, and getting this document wrong is not a paperwork problem. A lawyer with data protection experience should read it before it is published, and the open questions at the end are the ones to put in front of them first.

Every factual claim below was re-checked against the code on 2026-08-17 and cites where it lives, so a reviewer can verify rather than trust.

What that re-check changed, so the diff is not mistaken for cosmetics: the data table was missing four categories the schema actually holds (consent records, safety reports and blocks, streak-saver events, erasure requests); it cited a team_pool table that does not exist, now corrected to team_season_pot; the trainer tips feed and the public website's click counters were not described at all; and the processors section has gone from "needs naming" to naming the three that are self-hosted and isolating the two that genuinely still need an answer.


1. Who we are

SkillStreak is an app for youth floorball players, built by their coach. The controller of the personal data described here is the project owner.

To be completed before publication: legal entity name, postal address, and a contact email address for data protection questions. A privacy policy with no reachable controller is not compliant, and this is the one gap the code cannot fill in.

2. Who uses the app, and what that means here

Two very different groups:

The strictest rules follow the children, so they are described first.

3. What we collect about a player, and why

DataWhyWhere it lives
Screen nameSo teammates can recognise each otherplayer
Real name (optional)Only so a coach can match a screen name to a childplayer_private_info, encrypted at rest
Birth yearAge banding and the consent route (13+ may self-verify)player
Parent/guardian contactTo ask for consent, and nothing elseplayer_private_info, encrypted
Training log entriesThe streak and the team's shared point pooltraining_log_entry
Video clipsThe team-only clip feedObject storage; metadata in video_clip
Chat messagesTeam chatteam_chat_message
Badges, streaks, pointsThe game itselfbadge_award, team_season_pot
Consent recordsProof that a parent approved, and whenparental_consent_record
Safety recordsReports of a clip or a chat message, and who a child has blockedclip_report, team_chat_message_report, team_chat_block
Streak-saver eventsThe "you didn't lose your streak" mechanicstreak_saver_event
Erasure requestsCarrying out an account deletion, and proving it happenedaccount_erasure_request

We do not collect location. Not from the device, not from a photo, not from a video. The app records that a child trained, never where. Video frames sampled for automatic tagging are stripped of all metadata (-map_metadata -1 in clip-frame-sampler.service.ts) precisely so a file cannot carry a location out of the app.

We do not use third-party analytics, advertising or tracking SDKs. There are none in the app's dependencies — this is checkable, not a promise.

A note on the safety records, because they are the row a reader is most likely to be surprised by: reporting a clip or a chat message, and blocking another player, necessarily record who did it. That is unavoidable — a report nobody can act on is not a safety feature — but it means a child's use of the safety tools is itself stored data, and a lawyer should be asked whether it needs saying more prominently than a table row.

4. Consent

5. What a child's data is NOT used for

6. Automatic clip tagging

Published clips may be analysed automatically to label the type of training shown — passing, shooting, fitness and similar, from a fixed list of eight.

Stated honestly:

7. Tips from trainers

The app has a reading feed of short coaching tips (trainer_post).

It is described here because it is content an adult outside the child's team publishes to children, which is a thing worth disclosing even though it collects nothing.

8. The public website

skillstreak.xyz counts two things, both as aggregate counters.

Link clicks — how often a few links are used ("get the app", "try it", and similar), one row per link per day (link_click).

Reads — how many times the page was opened, roughly how long it was open, and which language it was read in, one row per language per day (site_visit). Reading time is stored as a running total plus a count of how many reads reported one, so the site can say "a typical read is about two minutes" without keeping any individual visit.

Both are aggregate counters, not analytics. There is deliberately no cookie, no IP address, no session, no user agent, no referrer and no time of day, so the tables cannot answer "who visited" or "what did this one person read" — not because the data is protected, but because it was never collected. Nothing is stored on your device for either, which is also why the site shows no cookie banner: there is nothing to ask permission for.

The direct consequence, stated because it is a limitation and not a boast: the read count is page views, not people. One person opening the page three times counts as three. Telling them apart would need a per-visitor identifier, which is exactly the thing above that is not collected.

The signup form

The website also has a form for adults who want to hear from us. It is the one place on the public site that collects personal data about an identifiable person, so it is described separately from the counters above.

If you fill it in we store: your name, your email address, how you said you would like to be involved, the optional note you wrote, the language the form was in, and — if you arrived through a campaign link — the plain ?campaign= value from that link. There is no cookie and no tracking identifier behind that last one; it is simply part of the address you followed.

The lawful basis is your consent, and we record the moment you gave it rather than merely that you did. The two things you can ask for — news about new releases, and an invitation to a live demo — are stored separately and each records its own moment, because they are separate permissions. Ticking neither means we hold nothing to contact you about, and the form declines to submit.

Every message carries a link to remove yourself. Using it deletes the row outright — it is not a flag that stops the sending, and nothing is kept to remember that you left. Otherwise the entry is deleted after 365 days (see the table below) whether or not you ever hear from us.

This is adult data and is deliberately kept apart from anything the app knows about a child. It lives in its own table with no link to any player, team or training log; there is no field that could join them, and the only way to read it is a staff-only admin page. Someone filling in this form is a stranger who typed their address into a website, not a child under a parental-consent regime, and the two are never queried together.

9. How long we keep things

DataKept for
Video clips90 days
Bug reports90 days
Error logs90 days
Generated training plans (staff)365 days
Event registrations365 days
Account dataUntil the account is deleted

Each figure is a constant in the code (DEFAULT_CLIP_RETENTION_DAYS and its siblings), enforced by scheduled sweeps rather than by intention.

10. Deleting an account

A player can delete their own account from the app (Profile → delete account). Deletion removes their personal data, including clips, chat messages and training history, subject to the successor rules that apply if they are a team captain.

11. Staff data

Staff sign in with Google, Microsoft or Apple. We store the email address and display name their provider returns, and a record of which teams invited them (staff_account, team_coach). We never receive or store their password.

12. Who processes this data

Unusually for an app of this kind, the whole software stack is self-hosted — no managed database, no third-party object storage, no external AI service. The hardware underneath it is rented, so the hosting provider sits beneath the first three rows even though no service of theirs appears in them:

WhatWhoThird party?
Application and databaseOur own Kubernetes clusterSoftware: none. Hardware: Safespring
Video and image storageMinIO, running in that same clusterSame
Automatic clip tagging and training-plan generationOur own GPU clusterSame
Email (consent links, approvals)Googlesmtp.gmail.com:587, sending as noreply@isstech.ioYes
Staff sign-inGoogle, Microsoft, AppleYes

The email arrangement is explicitly interim (owner's decision, 2026-08-17): mail goes out through Google's SMTP from an isstech.io address, which is a domain belonging to the owner's other work rather than to SkillStreak. A dedicated skillstreak.xyz mail domain and its own account are planned. Recorded here rather than left implicit because consent emails are the mechanism the entire parental-approval model rests on, so who carries them is not an incidental detail.

To be completed before publication, and these are genuinely open rather than rhetorical:

  1. Safespring — named by the owner, 2026-08-17. Rented hardware: Safespring owns the machines, the owner owns the data and runs everything on top.

A Swedish provider, which is the single most helpful fact in this whole section: it means the largest concentration of children's data here — the database, every video clip, every chat message — is very likely to stay inside the EU/EEA, and the third-country transfer problem that dominates most GDPR reviews does not arise for it. Worth confirming in writing rather than assuming, since the answer should be easy to obtain and is load-bearing: which region or datacentre the resources actually run in, and whether any support or backup path reaches outside the EEA.

Still required: a data processing agreement. A caution for the lawyer's attention, because the reasoning that made this look settled does not carry the weight it appears to: owning the data is what makes the owner the controller, and that is the source of the obligations in this document rather than an exemption from them. A provider whose disks hold children's personal data is normally a processor however the ownership is described, and a DPA is what governs that relationship. Dedicated hardware narrows what the provider can reach and encryption at rest narrows it further — both worth raising — but neither replaces the agreement. A provider of Safespring's kind will have a standard DPA available; it needs signing and filing, not negotiating.

  1. Whether the Google mail account is Workspace or consumer Gmail. This decides whether a data processing agreement is even available: Google offers one for Workspace, while consumer Gmail runs on consumer terms that do not include one. Since these are the emails carrying parental consent requests, an arrangement with no available DPA would be a real gap rather than a formality. The planned move to a dedicated skillstreak.xyz mail account is the natural moment to settle it.
  2. Data processing agreements with the hosting provider and with Google, plus confirmation of whether either implies a transfer outside the EU/EEA. Google's corporate parent is in the US, so this needs a real answer rather than an assumption.

13. Your rights

Under the GDPR you may request access, correction, deletion, restriction, portability, and may object to processing. For a child, a parent or guardian may exercise these rights. You may also complain to your national data protection authority — in Sweden, Integritetsskyddsmyndigheten (IMY).

To be completed before publication: the address these requests go to.


Open legal questions — not resolved here

Put these in front of a lawyer first:

  1. The controller's legal identity. A private individual running a service that processes children's data across several clubs may need a different structure. This affects the whole document.
  2. Legal basis for each purpose. This draft describes consent, but consent is not automatically the right basis for everything (service delivery, security logging, and abuse prevention often are not consent-based). Each purpose needs its basis named. The safety records in section 3 are the clearest example: a report or a block cannot sensibly rest on the reporting child's consent.
  3. Age of digital consent. It is 13 in Sweden but varies from 13 to 16 across the EU. The app's 13+ self-verification is correct for Sweden and may not be for a Finnish or German user — and the app already ships in eight languages.
  4. Automatic tagging under Article 22. It produces no decision with legal or similarly significant effect today, so Article 22 likely does not apply — but that conclusion should be confirmed rather than assumed, and it changes if tags ever drive badges or ranking.
  5. The cross-team clip feed, now designed but still not built. Existing parental consent covers team-only visibility. Publishing a child's clip beyond their team would need fresh consent, and this document must be updated before that ships, not after. The design is ADR-0019 as amended by ADR-0030, whose whole mechanism is a separate, revocable, default-off parental consent obtained precisely so that no existing family's team-only promise is reinterpreted. That design is the thing to put in front of the lawyer alongside this document — not after it ships.
  6. Processors — now named, agreements outstanding. See section 12. All of them are identified: Safespring for hardware, Google for mail, and Google/Microsoft/Apple for staff sign-in. What remains is paperwork rather than discovery — a DPA with Safespring, and the Workspace-versus-consumer-Gmail question that decides whether a DPA with Google is even available.
  7. Transfers outside the EU/EEA. Much smaller than it first looked. Safespring being Swedish means the bulk of the data — database, clips, chat — very likely never leaves the EEA, subject to confirming the region. What remains is Google: a US parent carrying the consent emails, and the staff sign-in identity providers. Those are the transfer questions worth the lawyer's time; the hosting one probably is not.