Privacy and data retention
What the osu!trans bot stores about members, why, for how long, and who can see it.
In the server, /privacy shows what it holds about you, and can export it or delete it.
1. Principles
- Collect what a feature needs to work, nothing for "maybe later".
- Nothing is kept forever by default. Every data class has a retention rule enforced by a tested job.
- Sensitive things (safety reports, screening answers, restricted tickets) are visible to the fewest people possible, and every view is logged.
- Aggregate statistics never identify a member.
- Members can see, export and delete what we hold about them, within the limits of keeping the server safe (moderation records about someone are kept while they matter).
UK GDPR's storage limitation principle is the yardstick: personal data is not kept longer than needed for the purpose it was collected for.
2. What we store
| Data | Why | Retention | Who can see it |
|---|---|---|---|
| Discord user id, display name snapshot | Everything references members | While referenced | Staff by capability |
| Moderation cases and private notes | Safety, accountability | While a member, then 2 years after leaving, then anonymised | Staff with case capabilities |
| AutoMod detections and context snapshots | Review and tuning | 30 days; context 14 days | Staff with AutoMod review |
| Reports | Safety | 1 year after closure, or as long as a linked case | Report reviewers |
| Staff applications (answers, age range, staff votes and notes) | Choosing staff | Drafts 2 days; declined 90 days and accepted 1 year after the decision | Application reviewers |
| Appeals (what the member wrote, the decision and a staff-only note) | Fairness | As the case | Appeal reviewers; the member sees only the outcome |
| Tickets and transcripts | Support | 180 days (normal), 1 year (restricted) after closing, then a stub (number, category, dates, rating; nobody's id, not even the opener's); tickets that never opened, 30 days | Staff with the category capability |
| Onboarding answers | Assigning roles, reviewing access | 30 days after completion | Screening reviewers |
| Introductions | Members chose to share them | Until withdrawn, or 7 days after leaving | Public in #introductions once approved |
| Custom pronouns | Shown where the member chose | Until changed or the member leaves | Where the member shows them |
| Country (also kept when it has no role) | Shown where the member chose | Until changed or the member leaves | Where the member's role or introduction shows it |
| Self-assigned role picks | Role panels | Not stored: they are Discord roles, and picks are not written to the audit trail | Anyone who can see the member's roles |
| Saved roles on leave | Restoring on return | 90 days | Nobody browses these |
| osu! link (osu! user id, username, main mode, stable or lazer scores, whether others can look it up by mention, whether it shows on server leaderboards) | osu! features | Until unlinked | The member; staff for safety |
| osu! link history (Discord id, osu! user id, link or unlink, when; no usernames) | Safety checks and the 24 hour relink cooldown | 1 year, also after an unlink | Staff with osu.links.view; each view is audited |
| osu! linking attempts (hashes only, never a usable token; after sign-in, the osu! id and username waiting for confirmation) | Finishing a sign-in safely | 10 minutes to sign in, 10 more to confirm; deleted on confirm, cancel or unlink, otherwise a day after expiry | Nobody |
| Score tracking opt-ins (server, mode, place and pp threshold) and quiet hours (two hours and a time zone) | Posting a member's new top plays, only after they opt in | Until they opt out or unlink | The member; staff see how many are tracked |
| Tracked plays (the score osu! published, its map, the post's status) | The tracking post, and evidence of activity for team leaders | 30 days; deleted at once on unlink | The server channel staff chose, when posted |
| osu! team data (the server's teams, members' public usernames, last visit when shown, ranks, daily team rank) | Team roles, the team panel and leader tools | Members until they leave the team; daily records 30 days | Anyone for the panel; team leaders and staff for the leader tools |
| osu! user tokens (only if needed) | Features that need the member's authority | Not kept today: the sign-in token is used once to read the account, then revoked. If a feature needs one: until unlinked or revoked; encrypted | Nobody; never displayed |
| osu! profile, score, beatmap and search cache (public osu! data; never previous usernames, which are dropped before anything is stored) | Fewer requests to osu!, data while osu! is down | Refreshed on use; cached scores and searches 30 days (and capped in size); profiles of players nobody here linked, and beatmaps that are not ranked, approved or loved, 30 days after their last fetch (ranked, approved and loved maps stay as the recommendation index: public map data, nothing about who played them); a member's cached profile and scores, and cached leaderboards and searches including them, are deleted on unlink | Anyone who looks the profile up |
| Linked Roles connection (the member's Discord tokens for this application, sealed with AES-256-GCM; the scopes granted; when it was set up and last updated; a hash of what was last sent) | Keeping the member's Linked Roles numbers current: linked or not, global rank, pp, main mode, team | Until they unlink osu!, delete their data, or revoke the bot in Discord; then Discord is told, the authorization revoked and the row deleted. Someone who signs in without an osu! link is told to link first and nothing is kept | Nobody; the tokens are never displayed or exported |
| Linked Roles sign-ins (hashes of the state and the browser cookie, and a keyed hash of the visitor's IP address to cap sign-ins per address; nothing that names anyone) | Finishing a sign-in safely | 10 minutes to use; deleted a day after expiry | Nobody |
| Score snapshots and profile history (one row a day per mode: pp, ranks, accuracy, play count) | Tracking, graphs, server leaderboards, recommendations | 1 year while linked; deleted on unlink | Anyone who runs /graph on them (as for their public osu! profile); aggregates in server leaderboards unless they turn those off |
| Recommendation history and feedback | Personalisation, evaluation | While linked; deleted on unlink | The member; aggregates for evaluation |
| Member timeline events (joins and the invite used, name, avatar, role changes, gate decisions) | Moderation context | While a member, then 1 year after leaving | Staff with case access |
| Profile check results | Safety review | 1 year | Staff with case access |
| Names and avatar hashes of banned members | Ban evasion detection | While the ban stands and a ban evasion rule is on; checked against Discord's ban list daily | Nobody browses these; a match shows staff the names that matched |
| Voice room records | Ownership, cleanup | 30 days after the room closes | Staff with voice override |
| XP totals and daily XP (never message content) | Levels and leaderboards | Totals while a member, deleted on opt-out or 90 days after leaving; daily totals 13 months | Everyone, unless the member hides from leaderboards |
| Giveaway entries | Drawing winners | 90 days after the draw; winners in the audit trail 1 year | Staff with giveaways.manage |
| Birthdays (month and day; time zone and birth year only if given) | Celebrating the member | Until removed, or 30 days after leaving. After removal only two things stay, neither with a date: when it was last changed, for up to 30 days, so the limit on changes holds; and which years the member was celebrated, until the end of the next year, so nobody is celebrated twice in a year | The member; others only if the member opts in to the listing, and never the year unless they choose to show their age |
| Bot poll votes | Counting, letting members change their vote | 30 days after the poll closes; totals kept. A vote is stored under a keyed hash of the voter, never their member id, with a random key per poll. While the poll is open, someone with database access and the member list could still work out who voted for what; the key is destroyed at the close, and from then on no vote can be tied to anyone | Nobody sees who voted for what |
| Suggestions (the idea, its author, staff's decision and note) and votes (member id and for or against) | Showing and deciding suggestions | With their votes, a year after the decision, or a year after they were made if never decided | Everyone sees the idea and the counts; nobody sees who voted which way |
| Event answers (member id, going, maybe or can't go) | The RSVP card and reminders | 30 days after the event ends or is cancelled; the event a year | Everyone sees the count and the first 15 going |
| Announcements (staff text, who wrote it, when it went out) | Previews, scheduling | Unsent drafts 30 days; the rest a year | Staff with announcements.post |
| Notification preferences (kinds turned off, quiet hours and time zone, daily DM limit) | Holding back DMs and pings the member did not want | Until the member resets them | The member |
| Daily DM counts (member id, day, how many) | The member's daily DM limit | Two days | Nobody |
| Structure snapshots (roles, channels, overwrites; a member id appears only where a channel has a per-member overwrite) | Recovering from a nuke | The newest 30 per server, plus one a day for 14 days | Staff who can change security settings, through recovery previews |
| Replays sent for rendering | Making the video the member asked for | The file is not kept by us; o!rdr holds the replay and the public video under its own rules. The bot sends o!rdr the member's Discord id with it, so o!rdr can limit renders per person | Public on o!rdr |
| Render records (who asked, where, the map and player as a title, a checksum of the replay file, o!rdr's render id and video link or failure) | Updating the render's message after a restart, posting a video again instead of rendering it twice | 90 days after the render ends | The channel it was asked in sees the message |
| Render settings (skin, resolution, dim, cursor size, three toggles) | The member's next renders | Until the member resets them | The member |
| Audit events | Accountability | 1 year | Admins |
| Dashboard accounts (Discord id, display name, avatar link; no email, no Discord tokens) | Signing staff in | While they hold a staff capability; a lost role ends access at the next request | Admins |
| Dashboard sessions (with the IP address and browser that started them) | Sign-in, revocation | 7 days, deleted on sign-out | Admins, for revoking |
Message content is not stored, except: ticket transcripts (the point of a ticket), AutoMod context snapshots (short-lived), and evidence a staff member explicitly preserves on a case.
3. Member controls
/privacyshows what the bot holds about the caller, grouped as above, with buttons to export (a JSON file in DMs) or delete the deletable parts./osu unlinkdeletes everything osu!-related except bookmarks, which are the member's own list (/privacydeletes those)./intro withdrawdeletes the introduction.- Moderation records, reports about the member and closed tickets are not deletable by the member; the page says so and explains how to ask staff.
4. Analytics
The dashboard shows counts and rates. It never shows restricted ticket content, report text or screening answers in charts or overviews. Small counts that could identify someone (fewer than 5) in restricted categories are shown as "under 5".
5. Third parties
- Discord receives what any bot sends to Discord, and, for members who set up Linked Roles, their osu! username, main mode, global rank, pp and whether they are in a server team, which Discord shows on their profile as a connection.
- osu! receives API requests identifying osu! user ids we look up.
- No analytics services, no error tracking service that receives message content, no AI services.