Legal Document
Privacy Policy
Gait collects behavioral metadata — never message content — to detect automated and bot accounts on Discord. This document explains exactly what we collect, how it's anonymized, and your rights.
01 What Gait Is
Gait is a behavioral bot-detection tool for Discord server moderators. It operates as a Discord bot that observes behavioral metadata — timing patterns, interaction cadence, account characteristics — to produce a probabilistic score indicating the likelihood that a Discord account is automated (bot, script, or AI agent). Scores are made available to guild administrators ("server admins") to help them moderate their communities.
02 Who Controls Your Data
Guild administrators are data controllers
Discord guild (server) administrators choose to install the Gait bot. By doing so, they become the data controller for the behavioral signals collected from members of their server. Guild admins determine whether Gait is installed, the alert threshold for notifications, and whether to act on a score.
Gait is a data processor
Gait processes data on behalf of guild administrators under their instruction. Gait does not sell data, does not use data for advertising, and does not share data with third parties.
03 What Data Is Collected
Gait collects behavioral metadata only. No message content, usernames, display names, or avatars are stored. The tables below list exactly which signals are recorded, sourced directly from the bot's event handlers.
Guild join
| Field | Description |
|---|---|
account_age_days | Age of the Discord account in days at join time |
has_avatar | Boolean — whether the account has a custom avatar set |
has_default_avatar | Boolean — whether the account uses Discord's generated default avatar |
username_entropy | Shannon entropy of the username string — a statistical measure of character randomness. The username text itself is never stored. |
public_flag_count | Count of Discord public flags (e.g. Early Supporter, HypeSquad). Individual flag types are not stored, only the count. |
has_nitro | Boolean — whether the account holds an active Nitro subscription at join time |
Message activity
| Field | Description |
|---|---|
msg_length | Character count of the message (not the text itself) |
has_attachment | Boolean — whether the message included a file attachment |
has_embed | Boolean — whether the message included a link embed |
mention_count | Number of user mentions in the message |
is_reply | Boolean — whether the message is a reply to another message |
reply_latency_ms | Milliseconds between the parent message and this reply (only when is_reply is true) |
typing_duration_ms | Duration of the typing indicator before send, in milliseconds. Ephemeral — never persisted independently. |
Message edits
| Field | Description |
|---|---|
msg_length | Character count of the edited message |
edit_latency_ms | Milliseconds between original send and the edit |
Reactions
| Field | Description |
|---|---|
reaction_latency_ms | Milliseconds between the message's creation and the reaction being added |
emoji_category | Coarse category: custom, face, hand, or symbol. The specific emoji is not stored. |
message_age_ms | Age of the reacted-to message at the time of reaction |
Voice activity
| Field | Description |
|---|---|
duration_ms | Duration of the voice session in milliseconds |
was_muted | Boolean — whether the user was self-muted |
was_deafened | Boolean — whether the user was self-deafened |
Presence changes
| Field | Description |
|---|---|
old_status | Previous status string (online / idle / dnd / offline) |
new_status | New status string |
client_is_mobile | Boolean — connected via mobile client |
client_is_desktop | Boolean — connected via desktop client |
client_is_web | Boolean — connected via web client |
Server departure
When a user leaves or is removed from a server, only the anonymized user identifier and a timestamp are recorded. No other properties are captured.
What is explicitly NOT collected
| Data type | Status |
|---|---|
| Message content (text) | Never collected, stored, or transmitted |
| Usernames / display names | Used transiently to compute entropy, then discarded |
| Avatar images or URLs | Never collected |
| Email addresses | Never collected |
| IP addresses | Never collected |
| Voice audio | Never collected — only session duration and mute/deafen flags |
| Direct messages (DMs) | Bot ignores all non-guild events |
| Bot account activity | All event handlers filter out bot accounts |
04 How User Identifiers Are Anonymized
Gait never stores a raw Discord user ID anywhere — not in databases, not in logs, not in API payloads.
Discord User ID (snowflake)
│
│ HMAC-SHA-256(user_id, secret salt)
│ — computed server-side within Gait —
▼
GIID (Gait Internal ID — the only user identifier ever
stored, sent in API payloads, or placed on the
internal message bus) Your Discord user ID is run through a one-way cryptographic hash (HMAC-SHA-256 with a secret salt) before anything is stored. Only the result — the GIID — is ever written to a database, included in an API payload, or placed on the internal message bus. The GIID cannot be reversed to reveal the original user ID, whether by Gait staff or through a database breach.
When you exercise your data rights (export or erasure), Gait's API re-derives your GIID from the user ID you supply using the same one-way hash, in order to locate your records. The raw user ID is used only transiently for that lookup and is never stored.
A strict property allowlist is enforced before any event leaves the bot process. Any property not on the allowlist is silently dropped, preventing accidental transmission of unanticipated fields including message content.
05 Cross-Server Data Aggregation
Gait observes behavior across every Discord server where it is installed. Behavioral signals from all servers are aggregated under a single GIID per user.
Discord users who are members of Gait-monitored servers have no direct mechanism to opt out of data collection at this time. Server admins can remove Gait from their server to stop future collection for that server's members.
06 What Is Computed From the Data
| Dimension | What it measures | Signals used |
|---|---|---|
dim_temporal | Regularity of timing patterns | Inter-message interval variability, reply latency variability, typing-speed variability |
dim_content | Variability in message characteristics | Message length distribution, edit rate |
dim_lifecycle | Account maturity indicators | Account age, username entropy, custom avatar presence |
dim_social | Social interaction patterns | Reserved for Phase 2 — hardcoded to 0.5 (neutral). Has no effect on current scores. |
The final score is a weighted mean of these dimensions. A minimum number of behavioral data points must be collected before a score is computed; the exact threshold may be tuned over time based on scoring quality. Scores below 0.45 trigger an alert to server admins.
07 Data Storage and Retention
TimescaleDB — behavioral time-series
| Table | Contents | Retention |
|---|---|---|
behavioral_events | Raw event records (GIID, event type, timestamp, properties) | 72 hours — automatic rolling deletion |
account_features | Computed feature vectors | 90 days — automatic rolling deletion |
PostgreSQL — account and scoring store
| Table | Contents | Retention |
|---|---|---|
accounts | One row per GIID: first seen, last seen, data point count | 730 days of inactivity — automated nightly purge |
scores | Current score, classification, dimension scores per GIID | 365 days — automated nightly purge |
feedback | Admin actions on alerts | 365 days — automated nightly purge |
alerts | Alerts sent to server admins | 180 days — automated nightly purge |
Automated retention is enforced by a scheduled job that runs daily at 03:00 UTC.
08 Who Can Access Stored Data
| Data | Accessible by |
|---|---|
| Behavioral events (72h window) | Worker process (feature extraction only) |
| Feature vectors | Worker process (scoring) and API (internal only) |
| Scores and classifications | Guild admins via bot command; Gait platform operators |
| Alerts | Guild admins in their configured alert channel; Gait operators |
| Admin feedback/labels | Gait operators (used for model evaluation) |
GIIDs are never exposed to end users. Score queries return the score, classification, and dimensional breakdown only. The GIID is, however, included in the responses of the operator-only data-rights endpoints (GET /v1/data-rights/export and DELETE /v1/data-rights/erase), which require an API key and are used by guild admins and Gait operators to fulfil access and erasure requests — it serves there as a stable, one-way reference handle for correlating the export with internal records. The end-user self-service surfaces (/gait my-data and /gait forget-me) never return a GIID.
09 Your Rights (GDPR / CCPA)
Right of access
Guild admins can request a full machine-readable export of all data held for a user via
GET /v1/data-rights/export.
The response includes all behavioral events, feature vectors, scores, feedback, and alerts for
that GIID. There is no end-user self-service portal; requests must be routed through a guild admin
or submitted to Gait directly via the contact in Section 12.
Right to erasure
Any Discord user can erase their own data by running the
/gait forget-me command in any server where Gait is installed.
The command requires no admin permission and erases all data for the requesting user
across every Gait-monitored server, not just the one the command is invoked in.
Because GIIDs are one-way HMAC hashes, deletion is irreversible. If you remain in
Gait-monitored servers afterwards, fresh signals will be collected under a new internal
identifier with no link to your prior history.
Guild admins can also trigger erasure on behalf of a user via the
DELETE /v1/data-rights/erase API endpoint.
Right to inspect your own data
Any Discord user can view a summary of the behavioral data Gait holds on their account
by running the /gait my-data
command. The summary shows when Gait first and last observed your account, how many data
points have been collected, your current score and classification, and how many servers
contributed signals — without exposing your internal identifier (GIID).
Right to object / opt out
Gait does not offer a "monitor everyone except me" mode. Members who do not want their
behavioral signals collected can erase their data on demand via
/gait forget-me,
or leave Gait-monitored servers, or request that a server admin remove Gait from the server.
CCPA — Do Not Sell
Gait does not sell personal data to third parties.
Open gaps
| Right | Status |
|---|---|
| Data access (admin-facing) | Implemented |
| Erasure (admin-facing) | Implemented |
| End-user self-service erasure | Implemented — /gait forget-me |
| End-user self-service data summary | Implemented — /gait my-data |
| Individual opt-out while staying in server | By design — erase, leave, or ask the server admin to remove Gait |
| Data portability (user-initiated) | Partial — JSON export available to guild admins |
10 Data Security
All identifiers are cryptographically hashed before storage using HMAC-SHA-256. The secret salt used in hashing is held only within Gait's own server-side services — never exposed to third parties or client-side code, and never written to any database or log.
API authentication uses bcrypt-hashed API keys. Raw keys are displayed only once at creation. All inter-service communication occurs within an isolated Docker network. Database ports are not exposed to the public internet.
11 Discord Terms of Service Compliance
Message Content Intent is used only to compute msg_length (character count). Message text is never stored or transmitted.
Server Members Intent is used to collect guild join and departure events.
Presence Intent is used to collect status change events. All three privileged intents are disclosed in the bot's Discord Developer Portal entry.
When Gait is removed from a Discord server, the bot immediately purges all
behavioral_events,
account_features,
alerts, and
guild_settings
records for that server. GIIDs with cross-server history retain their feature vectors for other servers they belong to.
12 Contact and Requests
To submit a data access request, deletion request, or privacy inquiry:
Email: [email protected]
Response time: within 7 days