PolarBot keeps everything in one SQLite file (see Files ), opened in WAL mode with foreign keys on and a 5 s busy timeout. Migrations run automatically at startup. Nothing about a flagged message is stored: the mod card in Discord is the only record. Every row of a server is deleted when the bot leaves that server.
Table What it holds Personal data Kept for
guild_settingsPer-server settings: log channel, log level, staff announcements channel. None (server and channel IDs). Until the bot leaves the server (then deleted at once).
role_levelsThe /perms mapping: role → permission level. None (role IDs). Until the bot leaves the server (then deleted at once).
mod_actionsPunishment history: bans, unbans, kicks, timeouts, untimeouts and warns, from commands and from the scanner. Yes: target and moderator user IDs, the reason text, the time. 180 days (purged hourly), or until the bot leaves the server.
warnings/warn warnings.Yes: user and moderator IDs, the reason text, the time. 180 days (purged hourly), or until the bot leaves the server.
scan_settingsScanner settings: on/off, thresholds, actions, mod role, channel mode, NSFW-link action. None. Until the bot leaves the server (then deleted at once).
scan_channelsScanner channel rules (monitor or exempt). None. Until the bot leaves the server (then deleted at once).
scan_exempt_rolesRoles the scanner skips. None. Until the bot leaves the server (then deleted at once).
scan_domainsThe server’s allow and block lists of domains. None. Until the bot leaves the server (then deleted at once).
training_examplesAnonymized texts of decided scanner cards (Scam / Not scam) for a future classifier. No: mentions, IDs, names, invite codes and URL paths are replaced before storing; no server or user column; the day only. Until exported with polarbot export-training (the export deletes them).
guild_oauthThe /perms authorize grant for command visibility: the refresh token, encrypted (AES-256-GCM, server ID as associated data). The user ID of the admin who authorized, and the encrypted token. Until replaced by a new authorization, found revoked, or the bot leaves the server.
bot_metaProcess-wide state, e.g. announced_version (the last version whose update notice was posted). None. Kept.
scan_stats/scanner status counters: messages flagged and acted on, per server per UTC day.None (two numbers per server and day). 30 days (purged hourly), or until the bot leaves the server.
_sqlx_migrationsWhich migrations have run (managed by sqlx). A binary refuses to start on a database migrated by a newer one. None. Kept.
Column Type Null Default Key
guild_idINTEGER yes – primary
localeTEXT no 'en'
log_channel_idINTEGER yes –
created_atINTEGER no –
log_levelINTEGER no 2
announcements_channel_idINTEGER yes –
Column Type Null Default Key
guild_idINTEGER no – primary
role_idINTEGER no – primary
levelINTEGER no –
Column Type Null Default Key
idINTEGER yes – primary
guild_idINTEGER no –
moderator_idINTEGER no –
target_idINTEGER no –
actionTEXT no –
reasonTEXT yes –
duration_secsINTEGER yes –
created_atINTEGER no –
Column Type Null Default Key
idINTEGER yes – primary
guild_idINTEGER no –
user_idINTEGER no –
moderator_idINTEGER no –
reasonTEXT no –
created_atINTEGER no –
Column Type Null Default Key
guild_idINTEGER yes – primary
enabledINTEGER no 1
log_thresholdINTEGER no 60
delete_thresholdINTEGER no 90
punish_thresholdINTEGER no 97
punish_actionTEXT no 'timeout'
timeout_secsINTEGER no 3600
hacked_actionTEXT no 'delete_timeout'
mod_role_idINTEGER yes –
allow_invitesINTEGER no 0
channel_modeTEXT no 'all'
actions_enabledINTEGER no 1
updated_atINTEGER no –
nsfw_actionTEXT no 'delete'
Column Type Null Default Key
guild_idINTEGER no – primary
channel_idINTEGER no – primary
ruleTEXT no –
Column Type Null Default Key
guild_idINTEGER no – primary
role_idINTEGER no – primary
Column Type Null Default Key
guild_idINTEGER no – primary
domainTEXT no – primary
listTEXT no –
Column Type Null Default Key
idINTEGER yes – primary
textTEXT no –
categoryTEXT no –
verdictTEXT no –
created_atINTEGER no –
Column Type Null Default Key
guild_idINTEGER yes – primary
encrypted_refresh_tokenBLOB no –
nonceBLOB no –
authorized_byINTEGER no –
scopeTEXT no –
updated_atINTEGER no –
Column Type Null Default Key
keyTEXT yes – primary
valueTEXT no –
Column Type Null Default Key
guild_idINTEGER no – primary
dayINTEGER no – primary
flaggedINTEGER no 0
actedINTEGER no 0
Column Type Null Default Key
versionBIGINT yes – primary
descriptionTEXT no –
installed_onTIMESTAMP no CURRENT_TIMESTAMP
successBOOLEAN no –
checksumBLOB no –
execution_timeBIGINT no –
Applied in order, once each, at startup (crates/polarbot/migrations).
File Changes
0001_core.sqlcreates table guild_settings, creates table role_levels, creates table mod_actions, creates index mod_actions_guild_target, creates table warnings, creates index warnings_guild_user
0002_scanner.sqlcreates table scan_settings, creates table scan_channels, creates table scan_exempt_roles, creates table scan_domains, creates table training_examples, creates index mod_actions_created_at, creates index warnings_created_at, fills scan_settings
0003_logging.sqladds column guild_settings.log_level
0004_oauth.sqlcreates table guild_oauth
0005_bot_meta.sqlcreates table bot_meta
0006_scan_stats.sqlcreates table scan_stats
0007_nsfw_links.sqladds column scan_settings.nsfw_action, updates scan_settings
0008_announcements_channel.sqladds column guild_settings.announcements_channel_id