Astro Moderation

Official Astro Moderation 1.0.0 documentation for installing and operating the Roblox moderation panel, Ban API enforcement, chat mutes, cases, permissions, investigations and webhooks.

On this page

Quick setup

Start here when installing Astro Moderation for the first time.

1. Put each supplied root in the correct service

ReplicatedStorage
`-- AstroModeration

ServerScriptService
`-- AstroModeration
    |-- Bootstrap
    `-- Config

StarterGui
`-- AstroModerationUI

StarterPlayer
`-- StarterPlayerScripts
    `-- AstroModerationClient

Keep the supplied names and hierarchy. The full Explorer structure appears in Installation.

2. Authorize your first administrator

Open ServerScriptService.AstroModeration.Config, then replace 123456789 with your trusted numeric Roblox UserId:

Access = {
    UserIds = { 123456789 },
    Group = {
        Enabled = false,
        GroupId = 0,
        UseMinimumRank = true,
        AllowedRanks = {},
        MinimumRank = 200,
    },
    UserPermissionProfiles = {
        [123456789] = "Administrator",
    },
    GroupRankProfiles = {},
    DefaultPermissionProfile = "DefaultModerator",
}

Do not use a username or display name. The public package intentionally authorizes nobody until you add your own UserId or group access.

3. Review the safety settings

Before testing, configure ProtectedUsers, confirm the permission profiles, and review the supplied reasons and durations. Player-data lookup and Discord delivery are disabled by default and should remain off until their integrations are configured. The default moderator profile cannot revoke punishments or use permanent actions.

4. Choose your output level

Keep normal output enabled during setup. Turn on verbose diagnostics only while troubleshooting:

Logging = {
    Enabled = true,
    DebugMode = false,
    PrintStartupSummary = true,
}

Set DebugMode = true for detailed test diagnostics. Set Enabled = false only after setup is clean if you want routine Astro server and client output silenced.

5. Enable only the Roblox services you use

  • Use TextChatService for chat mutes.
  • Enable Roblox ban APIs before testing bans or unbans.
  • Enable Studio API access only when intentionally testing persistent data in Studio.
  • Enable HTTP requests only when Discord webhooks are configured.
  • Use a published private test universe for realistic DataStore, MemoryStore, teleport and ban testing.

6. Run the first access test

Publish and restart the test server, join with the authorized account, then press Shift + M. Confirm that the panel opens and complete one temporary test case. Join with an unauthorized account afterward and verify that it cannot open the panel or retrieve moderation data.

Do not launch to staff until the complete Production launch checklist passes.

System overview

Astro Moderation 1.0.0 is a server-authoritative moderation suite for Roblox experiences. It connects four staff workspaces to one case system:

  • Execute resolves and confirms a player before a ban or chat mute is submitted.
  • Lookup loads a six-digit case directly or lists the case history for a confirmed user.
  • Investigate checks a player’s current experience presence and exposes controlled join, spectate and approved player-data tools.
  • Moderator Statistics summarizes the current staff member’s moderation activity.

The client is responsible for presentation, input and camera behavior. It does not decide who is staff, which action is allowed, how long an action may last, whether a target is protected, which private fields may be returned or whether a case may be changed. Those decisions are made again by the server.

What “server-authoritative” means here

Hiding or disabling a button is useful for staff usability, but it is not treated as security. A modified client still has to pass server authorization, permission, target, action, reason, duration, cooldown and case-state checks. Private reasons and player-data fields are filtered before the response is returned.

The public guide intentionally does not document internal request formats, remote names, storage-key layouts, validation order, anti-spam thresholds or camera-relay messages. Legitimate setup does not require those details. Security still comes from server-side validation rather than secrecy alone.

Product responsibilities

Astro Moderation provides the workflow and safeguards around moderation. The experience owner remains responsible for:

  • Choosing trustworthy staff and reviewing their permissions.
  • Defining fair reasons, durations and appeal procedures.
  • Following Roblox policy and applicable law.
  • Restricting access to private moderation records and Discord channels.
  • Testing the installed version in the actual experience before production use.
  • Keeping a backup before replacing, moving or upgrading scripts.

Before you install

Use a separate published test universe or a private test place when possible. Several Roblox services behave differently in an unpublished local session, so a successful Studio-only test is not a complete launch test.

Requirements

You need:

  1. Roblox Studio and permission to edit the target experience.
  2. A published Roblox experience for realistic DataStore, MemoryStore, teleport and ban testing.
  3. TextChatService for persistent chat-mute enforcement.
  4. Roblox ban API support enabled for official bans and unbans.
  5. Studio API access only when you intentionally test persistent data from Studio.
  6. HTTP requests enabled only if the Discord webhook integration is used.
  7. At least one trusted UserId or group rank configured before staff testing.

Do not paste a webhook URL into a public script, LocalScript, shared module, screenshot, support ticket or public repository. Keep it in the server-only Config module.

Decide these policies first

Before editing configuration, decide:

  • Which staff roles may open the panel.
  • Who may ban, chat mute, revoke, investigate, join or spectate.
  • Who may use permanent actions.
  • Maximum temporary ban and chat-mute durations by role.
  • Which accounts must always be protected.
  • Whether private reasons contain information that should remain inside Roblox or may also be delivered to Discord.
  • Which player-data fields are genuinely needed for moderation.
  • Whether Discord should receive public reasons, private reasons or no moderation data.
  • How players will appeal and how staff should reference a Case ID.

Installation

Keep the supplied package roots in their intended services:

ReplicatedStorage
`-- AstroModeration
    `-- Shared
        |-- Constants
        `-- UIProtocol

ServerScriptService
`-- AstroModeration
    |-- Adapters
    |   `-- PlayerStatsAdapter
    |-- Services
    |   |-- BanService
    |   |-- CaseIndexService
    |   |-- CaseService
    |   |-- ChatMuteService
    |   |-- DataStoreServiceWrapper
    |   |-- DiagnosticsService
    |   |-- InvestigationService
    |   |-- ModerationService
    |   |-- ModeratorStatsService
    |   |-- PermissionService
    |   |-- PlayerStatsService
    |   |-- PresenceService
    |   |-- RateLimitService
    |   |-- SpectateService
    |   |-- UserResolver
    |   `-- WebhookService
    |-- Utilities
    |   |-- CaseIdGenerator
    |   |-- FormatTime
    |   |-- Retry
    |   |-- Sanitizer
    |   `-- TableUtil
    |-- Bootstrap
    `-- Config

StarterGui
`-- AstroModerationUI

StarterPlayer
`-- StarterPlayerScripts
    `-- AstroModerationClient

Do not rename or move the package roots unless an official update specifically instructs you to do so. The normal developer configuration surface is:

ServerScriptService.AstroModeration.Config

Initial installation sequence

  1. Make a backup or version-control checkpoint of the place.
  2. Insert the complete package and confirm all four roots exist.
  3. Open the server Config module.
  4. Replace the example access entry with your own trusted UserId.
  5. Assign that UserId to the Administrator profile for initial setup.
  6. Leave player-data lookup and Discord delivery disabled until each integration is configured.
  7. Keep Testing.MockModerationActions off unless you are in an isolated test environment.
  8. Publish the test place and restart the server.
  9. Join with the authorized account and press Shift + M.
  10. Confirm that an unauthorized account cannot open or use the panel.

The panel state is created when the authorized player joins. Restart the playtest or server after changing access, permissions, feature flags, reasons or durations.

Required Roblox settings

Review the target experience’s security and communication settings:

  • Enable Studio API access only when Studio must read or write real persistent test data.
  • Enable HTTP requests when the Discord webhook is enabled.
  • Enable the official Roblox ban APIs for the experience.
  • Confirm the experience uses TextChatService before enabling chat mutes.
  • Test cross-server join behavior in places that are part of the same published universe.

First onboarding

Start with one owner account and a deliberately limited test profile. Avoid onboarding the entire staff team before the owner has completed an end-to-end test.

Access = {
    UserIds = { 123456789 },
    Group = {
        Enabled = false,
        GroupId = 0,
        UseMinimumRank = true,
        AllowedRanks = {},
        MinimumRank = 200,
    },
    UserPermissionProfiles = {
        [123456789] = "Administrator",
    },
    GroupRankProfiles = {},
    DefaultPermissionProfile = "DefaultModerator",
}

Replace 123456789 with the real Roblox UserId. Do not use a display name or username where a numeric UserId is expected.

  1. Owner access: confirm one explicit UserId can open every required workspace.
  2. Unauthorized access: confirm a second account receives no panel access or case data.
  3. Test profile: create or reduce a profile for normal moderators.
  4. Protected accounts: add owners, developers and service accounts.
  5. Reasons and durations: remove presets that do not match staff policy.
  6. Case flow: run an approved temporary test action and locate its Case ID.
  7. Case review: load the test Case ID and verify every field on the new Case Details page.
  8. Optional systems: configure investigation, player data, statistics and Discord one at a time.
  9. Staff rollout: add staff only after the expected role boundaries have been verified.

Features and configuration

The Features table disables major product areas independently. A disabled feature should be treated as unavailable even if a profile still contains the corresponding permission.

Feature Purpose
Bans Temporary and permanent official Roblox bans
ChatMutes Persistent TextChatService chat restrictions
Investigation Presence and investigation status
Spectating Session-scoped spectating in the current server
PlayerStatLookup Approved DataStore and leaderstat fields
ModeratorStats Moderator profile and activity totals
DiscordWebhook Optional server-to-Discord event delivery

Configuration map

Config area What it controls
Features Major optional systems
Access Explicit users, group access and profile assignment
Permissions Per-profile capabilities and duration caps
ProtectedUsers Accounts and rank relationships that cannot be targeted
Moderation Required reasons and custom input policy
Ban Roblox ban scope and Case ID suffix behavior
ChatMute Join notice and expiry checking behavior
Cases Page sizes, recent-case caching and Case ID reservation policy
Cooldowns Request pacing and abuse resistance
Reasons Approved action-specific reason presets
Durations Approved action-specific duration presets
Investigation Presence and spectate-session policy
StatLookup Approved player-data sources and output limits
ModeratorStats Statistics retention and caching
Webhook Discord endpoint, privacy and event switches
UI Shortcut, close behavior and animation timing
Logging Startup and diagnostic output
DataStores Persistent-data namespace and retry policy
Testing Test-only moderation behavior

Change one area at a time, restart the test server and retest the affected workflow. This makes configuration mistakes easier to isolate.

Logging and debug

Astro Moderation has one master output switch and a separate verbose debug mode under Config.Logging:

Logging = {
    Enabled = true,
    DebugMode = false,
    PrintStartupSummary = true,
}
Setting Behavior
Enabled Master switch for routine Astro server and client prints and warnings
DebugMode Adds verbose diagnostic details while Enabled is also true
PrintStartupSummary Shows or hides the normal startup configuration summary

Use DebugMode = true in a private test environment when diagnosing DataStore operations, permission lookups, Roblox service failures, player resolution, UI contract issues or optional integrations. Debug output may contain operational identifiers such as UserIds and Case IDs, so do not publish logs without reviewing them.

Set Enabled = false when you want routine Astro Moderation output disabled across the server and authorized clients. Fatal installation errors that happen before Config can load may still appear; those messages are intentionally retained because the logging setting is not yet available and the package cannot start.

Turning output off does not disable validation, auditing, moderation, cases or webhook delivery. It only controls console output. During initial setup and upgrades, keep output enabled until the startup checks and production smoke test are clean.

Access and permissions

Access answers “may this player use Astro Moderation at all?” A permission profile answers “what may this authorized player do?” Both conditions must pass.

Explicit UserIds and group access

Explicit entries in Access.UserIds are useful for owners and emergency administrators. Group access can use either a minimum rank or a list of exact accepted ranks. UserPermissionProfiles maps individual UserIds to profiles, while GroupRankProfiles maps group ranks to profiles.

When using group access:

  • Confirm the GroupId belongs to the intended group.
  • Prefer explicit rank-to-profile mapping when ranks have different responsibilities.
  • Review what happens when a rank changes.
  • Keep at least one trusted explicit owner UserId for recovery.
  • Test with accounts at, below and above every boundary.

Permission reference

Permission Allows
OpenPanel Opening and initializing the moderation panel
Ban Temporary ban actions within the profile cap
ChatMute Temporary chat mutes within the profile cap
PermanentBan Permanent bans; separate from Ban
PermanentChatMute Permanent chat mutes; separate from ChatMute
RevokeBan Server permission reserved for an authorized ban-revocation workflow; disabled in the default moderator profile and no Case Details button is included in 1.0.0
RevokeChatMute Server permission reserved for an authorized mute-revocation workflow; disabled in the default moderator profile and no Case Details button is included in 1.0.0
LookupCases Direct case and user-history lookup
ViewPrivateReasons Receiving private reasons in case detail
InvestigateUser Loading investigation status
JoinUser Joining an available target server
SpectateUser Starting and stopping a current-server spectate session
ViewPlayerStats Loading developer-approved player-data fields
ViewModeratorStats Loading the moderator statistics workspace

MaxBanDurationSeconds and MaxChatMuteDurationSeconds restrict temporary actions. A cap of 0 disables that temporary action for the profile. Permanent actions still require their dedicated permission.

Least-privilege examples

  • Chat moderator: panel, chat mute and case lookup; no bans, player data, join or spectate.
  • Senior moderator: temporary bans and mutes, lookup and investigation; no permanent actions. Add reserved revocation permissions only if the developer has supplied a separate authorized workflow.
  • Administrator: all operational permissions, including permanent actions and role-sensitive tools.
  • Reviewer: case lookup and permitted private reasons, but no enforcement or role-sensitive investigation tools.

Create separate profiles when responsibilities differ. Do not give every moderator the Administrator profile simply because it is faster to configure.

Protected users

ProtectedUsers is an additional server-side boundary around accounts that should not be targeted through the panel.

Use it for:

  • Experience owners and primary developers.
  • Automation or service accounts.
  • Accounts used for deployment or emergency recovery.
  • Staff roles that should require a separate escalation path.

AllowSelfModeration = false prevents moderators from targeting themselves. ProtectEqualOrHigherGroupRank can prevent action against peers or higher-ranked group members when group hierarchy is part of the access model.

Protected users are not a substitute for careful permissions. Test protected accounts with temporary, permanent and revocation workflows before staff launch.

Moderation workflow

The Execute workspace is intentionally staged to reduce wrong-player actions.

  1. Enter a username or numeric UserId, or choose someone from the current server list.
  2. Load the player and review the display name, username, UserId and avatar.
  3. Confirm the resolved identity.
  4. The confirmed player is now shared with Lookup and Investigate for the current session.
  5. Choose Ban or Chat Mute.
  6. Choose an approved reason or enter a permitted custom reason.
  7. Choose an approved duration or enter a permitted custom duration.
  8. Review public and private text.
  9. Submit and complete the final confirmation.
  10. Record the six-digit Case ID shown after success.

Changing the selected player on one workspace clears confirmation for that workspace until the new player is confirmed. Confirming the new player replaces the shared identity across Execute, Lookup and Investigate. Using Clear Selection clears the shared target from all three workspaces. Staff should match the numeric UserId whenever identity matters; display names are not unique.

Public and private reasons

The public reason may be shown to the affected player through Roblox or experience messaging. It should be concise, professional and safe to disclose.

The private reason is intended for authorized staff context. It may contain internal evidence references or review notes, but it should still avoid unnecessary personal information. Private does not mean secret if the team also sends it to Discord.

Submission safety

The server resolves the selected action, reason and duration again. It also checks the staff profile, target protection, active case state, text limits, request pacing and duplicate submissions. A modified interface cannot grant a permission that the server profile does not contain.

Reasons and durations

Reason and duration presets use stable Id values. The visible Name may be changed for staff readability without turning the name itself into an authorization token.

{
    Id = "CHAT_SPAM",
    Name = "Chat Spam",
    DefaultPublicReason = "Chat restricted for disruptive messaging.",
    DefaultPrivateReason = "Repeated spam or disruptive chat messages.",
    AllowedActions = { Ban = false, ChatMute = true },
}

Keep IDs unique. Use AllowedActions to prevent a reason from appearing for an unsuitable action. Keep public defaults neutral and put internal context in the private reason.

Duration presets

{
    Id = "SEVEN_DAYS",
    Name = "7 Days",
    Seconds = 604800,
    AllowedActions = { Ban = true, ChatMute = true },
}

Permanent is represented by its own preset and is still restricted by PermanentBan or PermanentChatMute. Removing the permanent preset from the interface does not replace the server permission check, and granting the permission does not force you to show the preset.

Custom input

When enabled, custom durations accept readable values such as:

  • 30m
  • 2h
  • 7d
  • 1w
  • Raw seconds

Custom values remain subject to the global maximum and the moderator profile’s action-specific cap. Custom reasons remain subject to required-field and length rules.

Bans and chat mutes

Roblox bans

Astro Moderation uses Roblox’s official ban and unban APIs. The Config can control universe scope, alternate-account behavior, device blocking and whether the Astro Case ID is appended to the public reason.

The default Case ID suffix supports appeals by giving the player a reference such as Appeal using Case ID: 123456. If you customize the format, keep the {CASE_ID} token and leave enough room within Roblox’s public reason limit.

Test bans in a published test universe. A local Studio session is not a reliable substitute for the complete Roblox enforcement path.

Persistent chat mutes

Chat mutes are stored independently from Roblox bans and enforced through TextChatService. The active restriction is checked when a player joins, remains in force across servers and expires according to its timestamp.

Temporary restrictions are restored automatically after expiry. The optional join notice can tell the player that a restriction is active without exposing a Case ID unless you choose to show it. Version 1.0.0 does not include a revocation control on the Case Details page.

Failed actions

If enforcement fails, the panel does not claim success. A failed audit record may be preserved so the team can distinguish an attempted action from an applied one. Optional secondary work—such as recent indexes, statistics or Discord delivery—does not redefine whether the Roblox action itself succeeded.

Cases and lookup

Each moderation attempt is assigned a unique six-digit Case ID. A case ties together the affected user, moderator, action, status, timing and documented reasons.

Case statuses

Status Meaning
Pending The case was reserved while the enforcement transaction was being completed
Active The moderation action is currently in effect
Expired A temporary action reached its expiry time
Revoked Authorized staff ended the active action early
Failed The attempt did not apply the intended moderation action

The Lookup list displays active temporary actions with a live remaining duration and completed temporary actions as expired. The included Case Details page is the main place to review the permitted fields returned for one record.

Lookup workflows

You can:

  • Enter a six-digit Case ID and load one record directly.
  • Resolve and confirm a player before loading their case history.
  • Search currently displayed cases by reason.
  • Open a row to review the user, moderator, Case ID, action, original duration, live remaining duration and permitted reasons.

Case Details page

The Case Details page presents the affected user and moderator side by side. It shows the original punishment duration separately from the live remaining time. Ban type is red, Chat Mute is orange, and the original duration uses green, orange or red according to its configured length. Active time remaining is red; a completed temporary action displays Concluded in green.

Public and permitted private reasons use the full configured text returned by the server. The page does not include internal notes, a case timeline or a revocation button in version 1.0.0.

Case IDs and appeals

Use the Case ID as the stable reference in internal review and player appeals. Do not use a username alone: usernames can change and display names are not unique. An appeal process can ask for the Case ID and then assign review to someone with lookup access but no enforcement permission.

Investigation tools

Investigation uses short-lived presence information to classify a target as unavailable, in the same server or in another eligible server of the experience.

Presence is intentionally temporary. It can become stale during shutdown, teleport or connection changes, so a join request checks the destination again before moving the moderator.

Join user

Join is only available to a profile with JoinUser. It is intended for published servers in the same universe. The destination must still be available and joinable when the request executes.

Common reasons a join cannot complete include:

  • The target left or teleported.
  • The target is already in the moderator’s server.
  • The destination is private or unavailable.
  • Roblox presence or teleport services are temporarily unavailable.
  • The join action is still on cooldown.

Spectating

Spectating requires the target to be in the current server. Sessions are created by the server, expire automatically and can be stopped manually. The camera returns to the moderator’s own character when the session ends or the target leaves.

Roblox does not expose another player’s exact local camera directly to the server. When exact-camera relay is enabled, the included target client supplies camera telemetry during the authorized session. Treat that view as a convenience, not tamper-proof evidence. The server bounds and rate-limits camera relay before forwarding it.

Player data lookup

Player-data lookup is optional and deny-by-default. Developers select the exact fields moderators may see; the system does not provide a general DataStore browser.

Normal integrations are configured under Config.StatLookup.Adapter. You do not need to rewrite the included adapter for a standard Roblox DataStore layout.

StatLookup = {
    MaxRows = 50,
    MaxNameLength = 50,
    MaxStringValueLength = 200,
    Adapter = {
        Enabled = true,
        IncludeLeaderstats = false,
        Sources = {
            {
                StoreName = "PlayerData",
                Scope = nil,
                KeyPrefix = "Player_",
                KeySuffix = "",
                RootPath = "Data",
                Fields = {
                    Coins = "Currency.Coins",
                    Gems = "Currency.Gems",
                    Level = "Level",
                },
            },
        },
    },
}

Source fields

Setting Meaning
StoreName The Roblox DataStore name
Scope Optional DataStore scope
KeyPrefix Text placed before the numeric UserId
KeySuffix Text placed after the numeric UserId
RootPath Optional dot-separated path into the loaded value
Fields Moderator-facing labels mapped to dot-separated scalar paths

For a key such as Player_12345, use KeyPrefix = "Player_" and an empty suffix. If the stored value is nested under Data, set RootPath = "Data".

Multiple sources

Add another entry to Sources when approved fields live in a different DataStore. Use clear labels so staff can tell similarly named values apart. Duplicate labels from different sources should be renamed rather than left ambiguous.

Leaderstats

Set IncludeLeaderstats = true to include scalar values from an online player’s leaderstats folder. Leaderstats are unavailable for offline users; configured DataStore sources may still load offline data.

Returned-value rules

Only explicitly mapped strings, finite numbers and booleans are returned. Nested tables, Instances, functions, userdata, threads, non-finite numbers, oversized names, oversized strings and rows over the configured limit are discarded.

Do not expose passwords, access tokens, payment information, raw anti-cheat evidence, private user-generated text or full save data. Grant ViewPlayerStats only to roles that need the approved fields.

Moderator statistics

The Moderator Statistics workspace helps staff understand their own activity. It can display:

  • Profile display name and identity.
  • Total moderation actions.
  • Ban and chat-mute totals.
  • Revocation totals when an authorized revocation workflow is used.
  • Rolling activity such as today, seven-day and thirty-day counts.

Statistics are operational summaries, not a replacement for case review. A secondary statistics failure does not undo a successful action, and cached values may take a short time to reflect a very recent event.

Use statistics for workload visibility and quality review, not as a quota that rewards unnecessary moderation.

Discord webhooks

Discord delivery is optional. It sends server-created embeds to a staff channel after supported case events. The webhook is a notification layer; Astro case records remain the authoritative moderation history.

Create the webhook safely

  1. Create or select a private staff-only Discord channel.
  2. In the channel integration settings, create a webhook dedicated to Astro Moderation.
  3. Copy the webhook URL once.
  4. Paste it only into ServerScriptService.AstroModeration.Config.
  5. Enable HTTP requests in the Roblox experience.
  6. Enable both Features.DiscordWebhook and Webhook.Enabled.
  7. Choose event switches and whether private reasons may be sent.
  8. Publish and test in a non-production server.
Webhook = {
    Enabled = true,
    Url = "PASTE_DISCORD_WEBHOOK_URL_HERE",
    Username = "Astro Moderation",
    AvatarUrl = "",
    IncludePrivateReasons = false,
    RetryAttempts = 5,
    MinimumIntervalSeconds = 0.25,
    QueueCapacity = 500,
    Events = {
        Ban = true,
        ChatMute = true,
        Unban = true,
        UnChatMute = true,
        ModerationFailed = true,
    },
}

The placeholder above is intentional. Never publish a real URL in documentation or screenshots.

Optional automatic threads with Needle

For cleaner staff discussions, add Needle to the Discord server so each Astro Moderation webhook message can automatically receive its own thread. After adding Needle, run:

/auto-thread channel: #channel-name include-bots: Include bots

Replace #channel-name with the same channel that receives the Astro Moderation webhook messages. Include bots must be enabled; otherwise Needle will not create threads for webhook or bot messages.

Supported event delivery

Event switch When a message is sent
Ban A ban is applied and its active case is finalized
ChatMute A chat mute is applied and its active case is finalized
Unban An authorized revocation workflow successfully removes an active ban and updates the case
UnChatMute An authorized revocation workflow successfully removes an active chat mute and updates the case
ModerationFailed An apply or revocation attempt fails; the embed includes its failure code and returned failure reason

The standard Case Details page does not include a revocation button in version 1.0.0. Enabling Unban or UnChatMute does not add one; those switches only control delivery after a supported authorized workflow completes.

What the embed contains

Supported messages can include:

  • A one-line action and Case ID summary above the embed.
  • Case ID.
  • Moderation action.
  • Affected user’s display name, username and UserId.
  • Action author’s display name, username and UserId.
  • Public reason without the appended Case ID appeal suffix.
  • Private reason when explicitly enabled.
  • Event timestamp.
  • Failure code and bounded backend reason when a moderation or revocation fails.

Mentions are disabled in the generated payload, preventing reason text or names from intentionally pinging Discord roles or users.

Private-reason policy

Set IncludePrivateReasons = false unless the Discord channel is approved to hold the same information as the case system. If enabled:

  • Restrict channel visibility and webhook-management permissions.
  • Review Discord retention, exports, bots and integrations.
  • Train staff not to put secrets or unnecessary personal information in reasons.
  • Remember that deleting a webhook does not delete messages already delivered.

Delivery behavior

Webhook delivery is queued so staff do not wait for Discord before the panel can finish the supported action. Temporary network failures and Discord rate limits may be retried according to Config. If delivery ultimately fails, Astro reports a redacted diagnostic and does not print the secret URL.

A webhook failure does not reverse a successful Roblox action. Conversely, a Discord message should never be treated as the only proof that an action succeeded; verify the Case ID in Lookup.

Protect and rotate the webhook

A Discord webhook URL contains the credential needed to post through that webhook. Anyone who obtains it may be able to send unwanted messages to the channel.

If the URL is exposed:

  1. Delete or regenerate the webhook in Discord immediately.
  2. Replace the Config value with the new URL.
  3. Search code history, screenshots, logs and shared messages for the old URL.
  4. Republish and restart servers that still contain the old configuration.
  5. Review unexpected channel messages and staff access.

Do not send the URL to product support. A redacted screenshot of the surrounding switches is enough for configuration help.

Webhook troubleshooting

Symptom Check
No messages at all Both enable switches, HTTP requests, a published server and the event-specific switch
URL warning Use an unmodified Discord webhook URL and confirm it was pasted only into server Config
Actions work but Discord is silent Review server diagnostics for a redacted HTTP or rate-limit failure
Public reason arrives but private reason does not IncludePrivateReasons is off, which is the safer default
Duplicate-looking Discord messages Confirm only one Bootstrap runtime and one UI package are installed

UI and staff experience

The default shortcut is Shift + M. Change it under Config.UI by setting OpenKey and RequireShift.

Staff usage guidance

  • Verify the numeric UserId before confirmation.
  • Use public reasons that are suitable for the affected player to read.
  • Keep private reasons factual and relevant.
  • Save the Case ID in appeal or incident records.
  • Stop spectating when the review is complete.
  • Use Lookup to verify action state rather than relying only on Discord.

UI customization

You may restyle Studio-owned GUI objects, but preserve names and hierarchy required by the client controller. After structural UI changes, run a full panel smoke test: every workspace, dropdown, target card, status label, case row, Case Details value and confirmation modal.

Avoid moving authoritative rules into UI code. A different label color or hidden button should never be the only restriction on a sensitive action.

Data ownership and upgrades

Astro Moderation uses its own persistent namespace for cases, active chat mutes, indexes and statistics. DataStores.Prefix separates this product’s records from unrelated experience data.

Do not change the prefix after production launch unless you intentionally plan a data migration. A new prefix appears to the running system as a new empty set of moderation data.

Upgrade practice

  1. Back up the place and current Config.
  2. Read the complete version entry on the product page.
  3. Compare new Config fields with your existing values.
  4. Preserve your access policy, protected users, reasons, durations, player-data mappings and webhook privacy choice.
  5. Upgrade in a test place first.
  6. Test existing case lookup and active chat-mute behavior.
  7. Roll out to production during a monitored window.

Never copy an old Config over a new version without reviewing newly added fields. Never paste a production webhook URL into a public comparison tool.

Backups and recovery

Roblox DataStores are service-owned; the model file is not a backup of live case data. Keep experience versions and source backups for code recovery. For operational recovery, document who can access case lookup, manage enforcement and rotate the Discord webhook.

Security hardening

Use this checklist as the minimum production posture:

  • Keep all secrets and private configuration in server-only code.
  • Use least-privilege permission profiles.
  • Keep an explicit owner UserId for administrative recovery.
  • Protect owner, developer and service accounts.
  • Keep self-moderation disabled unless there is a documented reason.
  • Do not expose whole DataStore records through player-data lookup.
  • Disable features that the staff team does not use.
  • Keep permanent actions restricted to a small role.
  • Keep Discord private reasons disabled unless explicitly approved.
  • Restrict Discord channel access and webhook-management permissions.
  • Review startup warnings after every configuration change.
  • Test unauthorized clients, not only normal button clicks.
  • Do not weaken cooldowns or input limits to make testing faster in production.
  • Do not treat client visibility, object names or UI state as authorization.
  • Keep evidence and sensitive personal information outside the panel unless necessary and permitted.

Safe information to share for support

When requesting help, share:

  • Astro Moderation version.
  • The affected workspace and visible status message.
  • Whether the test is Studio, private published or production.
  • Relevant feature switches with secrets redacted.
  • The first startup warning or error.
  • Clear steps to reproduce with test accounts.

Do not share webhook URLs, private reasons, access tokens, full production Config files, internal player save data or private case evidence.

Testing checklist

Access and permissions

  • Authorized owner can open the panel.
  • Unauthorized account cannot open it or retrieve data.
  • Every profile sees only its intended workspaces and actions.
  • Permanent actions fail for a profile without permanent permission.
  • Temporary actions above the role cap fail.
  • Protected users and self-targeting are rejected.
  • Equal-or-higher rank protection behaves as configured.

Execute

  • Username and UserId resolution identify the same account.
  • Server-player selection fills the correct profile.
  • Changing target clears confirmation.
  • Reasons appear only for their allowed actions.
  • Duration presets and valid custom duration formats work.
  • Missing or oversized reasons are rejected.
  • Double-clicking or repeating a submission does not create duplicate actions.
  • Success displays a six-digit Case ID.

Cases

  • Direct Case ID lookup loads the correct record.
  • User history returns expected cases.
  • Reason search filters visible rows.
  • Active temporary cases count down and expired cases show completed status.
  • The affected user and moderator identities populate the correct sides of Case Details.
  • Ban and Chat Mute type colors match the documented behavior.
  • Original duration and live remaining duration display independently.
  • Public and private reasons wrap correctly near their configured limits.
  • Private reasons follow the profile permission.

Chat mutes

  • A muted test account cannot send normal chat.
  • The mute persists after rejoin and server change.
  • Temporary expiry restores chat.
  • Permanent restrictions remain until revoked.

Investigation

  • Offline, same-server and other-server states display correctly.
  • Join refuses stale or unavailable destinations.
  • Spectate starts only for a target in the current server.
  • Stop, target leave, respawn and moderator respawn restore the camera.
  • A session expires without leaving the moderator camera stuck.

Player data and statistics

  • Only approved fields are returned.
  • Offline DataStore lookup uses the expected key format.
  • Leaderstats appear only for online users when enabled.
  • Nested or oversized values are omitted.
  • A profile without ViewPlayerStats cannot load data.
  • Moderator totals update after supported activity.

Discord

  • Each enabled supported event sends one embed.
  • Disabled events send nothing.
  • Private reasons follow the privacy switch.
  • Mentions in reason text do not ping Discord members.
  • A bad or unavailable webhook does not undo an applied moderation action.
  • The Case ID in Discord matches Lookup.

Troubleshooting

Start with the first Astro warning in Server output. Later errors are often consequences of the first configuration problem.

Symptom What to check
Panel does not open Authorized UserId or group rank, assigned profile, OpenPanel, shortcut and one installed client
Player cannot be resolved Correct username/UserId, Roblox service availability and request cooldown
Confirm button resets The selected target changed or was cleared; confirm the resolved identity again
Ban request fails Official ban APIs, published test environment, role permission, duration cap and protected target rules
Chat mute is not enforced TextChatService, ChatMutes feature, server runtime and active case status
Case cannot be found Exactly six digits, correct experience/DataStore namespace and persistent API availability
User history is empty Confirmed target, existing indexed cases and the same production namespace
Join user fails Published universe, fresh presence, joinable server and teleport availability
Spectate fails Target is in the same server, spectating is enabled and the profile is permitted
Player data says not configured Adapter enabled and at least one approved source or leaderstat option
Player-data values are missing Key format, scope, root path, field path and supported scalar type
Moderator stats look delayed Cache interval and successful completion of the underlying event
Discord receives nothing HTTP requests, both enable switches, event switch, URL and published-server test
UI object warning appears Required GUI object was renamed, moved, deleted or duplicated
Cooldown message appears Wait for the displayed category cooldown; do not repeatedly submit

Startup diagnostics

Startup checks can report duplicate preset IDs, invalid durations, an incomplete Case ID suffix, missing player-data mappings, webhook configuration conflicts and disabled HTTP requests. Fix the first reported issue, restart the test server and repeat the same workflow.

Roblox platform limitations

  • A Roblox experience cannot silently copy Case IDs to the system clipboard. Read-only TextBoxes allow normal selection where supported.
  • Exact spectate telemetry comes from the target client during an authorized session and is not authoritative evidence.
  • Presence is an expiring hint and can briefly be stale during teleports or crashes.
  • Roblox unban behavior operates on the user at the configured scope; Astro records which internal case authorized the operation.
  • Service outages and budgets can affect DataStore, MemoryStore, teleport, thumbnail, Discord and ban operations independently.

Production launch checklist

Before opening the panel to the full staff team, confirm:

  1. The experience and moderation package are backed up.
  2. Product version is 1.0.0 and the release notes were reviewed.
  3. Only intended UserIds and group ranks are authorized.
  4. Every profile follows least privilege.
  5. Owners, developers and service accounts are protected.
  6. Reasons, durations, public wording and appeal policy are approved.
  7. Permanent actions are limited to the intended role.
  8. Ban and chat-mute workflows were tested in a published test universe.
  9. Case lookup, user history, Case Details and expiry display were verified.
  10. Investigation, join and spectate behavior were tested if enabled.
  11. Player-data lookup exposes only approved fields.
  12. Discord uses a private channel, a dedicated webhook and the intended privacy setting.
  13. No secret appears in shared code, screenshots or support material.
  14. Startup output contains no unresolved Astro configuration warning.
  15. Unauthorized and hostile-input tests were completed.
  16. Staff received a short policy covering confirmation, reasons, Case IDs and appeals.

After launch, review permissions and protected users whenever staff roles change. Treat a webhook exposure, unexpected permanent action or private-data disclosure as an operational incident and respond immediately.

Scope and purchase expectations

Astro Moderation 1.0.0 is a Roblox model/source package. The buyer installs it in Roblox Studio, configures it for their experience and tests it with their own staff, data model and enabled Roblox services. It is not a hosted moderation service and does not include ongoing staff, automatic exploit detection, evidence collection, an appeal website, a Discord bot or custom migration of an existing admin system.

Included in version 1.0.0

  • An included moderation UI with Execute, Lookup, Investigate and Moderator Statistics workspaces.
  • Temporary and permanent Roblox ban workflows when the experience enables the required Roblox APIs.
  • Persistent TextChatService chat mutes with join and expiry enforcement.
  • Six-digit Astro Case IDs, direct case lookup and indexed user case history.
  • A Case Details view for the affected user, moderator, action type, original duration, live time remaining, public reason and permitted private reason.
  • Shared confirmed-player selection across Execute, Lookup and Investigate.
  • Configurable access profiles, duration caps and protected-user rules.
  • Optional presence, join, spectate, approved player-data lookup, moderator statistics and Discord webhook delivery.
  • Server-side validation, request pacing, duplicate-submission protection and startup diagnostics for the supported workflows.

Not included in version 1.0.0

  • Internal case notes.
  • A case-event timeline.
  • A Case Details revocation button or a complete appeals interface.
  • Automatic anti-cheat detection or automatic evidence gathering.
  • A hosted database, hosted dashboard, external staff portal or managed Discord bot.
  • Automatic compatibility with custom chat, admin, camera, teleport or DataStore frameworks.
  • Automatic conversion of another moderation system’s historical data.
  • Guaranteed uptime for Roblox, Discord or any other third-party service.

Player-data lookup requires the buyer to map explicitly approved fields from their own DataStore or leaderstats layout. Structural changes to the supplied UI can also require matching controller updates. Review this scope, the requirements above and the current product version before purchase or production use.

Marketplace refunds and reimbursements are handled by Roblox under the applicable Creator Store policies and any rights required by law. Nothing in this documentation overrides those policies or legal rights.