Legal Document
Gait collects behavioral metadata — never message content — to score whether a Discord account is operated by a real human or an automated system. This document explains exactly what we collect, how it's anonymized, and your rights.
Gait is a human authenticity scoring platform. It operates as a Discord bot that observes behavioral metadata — timing patterns, interaction cadence, account characteristics — to produce a probabilistic score indicating whether a Discord account is operated by a real human or an automated system (bot, script, or AI agent). Scores are made available to guild administrators ("server admins") to help them moderate their communities.
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 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.
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.
| 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 |
| 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. |
| Field | Description |
|---|---|
| msg_length | Character count of the edited message |
| edit_latency_ms | Milliseconds between original send and the edit |
| 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 |
| 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 |
| 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 |
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.
| 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 |
Gait never stores a raw Discord user ID anywhere — not in databases, not in logs, not in API payloads.
Your Discord user ID is run through a one-way cryptographic function twice before anything is stored. The result (the GIID) cannot be reversed to reveal the original user ID — not by Gait staff, not through a database breach.
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.
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.
| 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 of 50 data points must be collected before a score is computed. Scores below 0.45 trigger an alert to server admins.
| 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 |
| 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.
| 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.
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.
Guild admins can trigger a full erasure for a user via
DELETE /v1/data-rights/erase.
This permanently deletes all records for that GIID across both databases. Because GIIDs are
one-way HMAC hashes, deletion is irreversible. If you remain in Gait-monitored servers,
fresh signals will be collected and a new GIID will be derived, beginning a new scoring history.
There is no technical mechanism for individual users to opt out while remaining a member of a Gait-monitored server. Opting out requires leaving the server or requesting that the server admin remove Gait.
Gait does not sell personal data to third parties.
| Right | Status |
|---|---|
| Data access (admin-facing) | Implemented |
| Erasure (admin-facing) | Implemented |
| End-user self-service portal | Open — requests via guild admin or Gait contact |
| Individual opt-out while staying in server | By design — server admin is the data controller |
| Data portability (user-initiated) | Partial — JSON export available to guild admins |
All identifiers are cryptographically hashed before storage using HMAC-SHA-256. The platform salt used in hashing is stored only in the bot's runtime environment and is 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.
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.
To submit a data access request, deletion request, or privacy inquiry: