Channel ordering
Keep channel-order audit behind its own capability gate, pinned application and bot identities, and non-empty exact guild allowlist inside the read-guild boundary. Reviewed changes require a second independent toggle. Do not derive audit or mutation authority from ordinary channel reads, channel metadata, channel creation, guild scaffolds, forum tags, permission overwrites, event-feed scope, channel-only read scope, a target name, or another administrative feature. A client without MCP elicitation must not execute channel-order changes.
Build audit evidence from one coherent complete Gateway layout plus one bounded HTTP guild-channel snapshot taken between equal layout revisions. The Gateway projection may contain only exact channel ID, documented direct-channel type, nonnegative raw position, nullable parent ID, and explicit CHANNEL_OBFUSCATED state. Before Discord's November 16, 2026 HTTP transition, accept a strict complete HTTP inventory. After or during obfuscation testing, accept only the strict exact non-obfuscated Gateway subset. Select the evidence mode from the observed sets rather than the local clock. Discard HTTP metadata for every Gateway-obfuscated channel even when HTTP still returns it. Reject missing, extra, duplicate, malformed, cross-guild, topologically invalid, or revision-drifting evidence.
Canonicalize every sortable group by ascending raw position and ascending snowflake ID. Categories form one guild-level family. Text, announcement, forum, and media channels form one text-like family per parent. Voice and Stage channels form one voice-like family per parent. Directory and unknown future channel types are unsupported, and an unsupported sibling at either affected parent must block a real change. Permit only one exact target immediately above or below one distinct same-family anchor. When the parents differ, derive the destination only from the exact anchor, require a valid root category or guild root, enforce category capacity, preserve the target's exact permission overwrites with literal lock_permissions: false, and never accept an arbitrary parent. Never accept arbitrary numeric positions, fuzzy names, caller-provided bulk payloads, cross-family moves, permission synchronization, permission or overwrite changes, flag or metadata changes, creation, deletion, retry, rollback, compensation, or reconciliation.
Require complete guild-level MANAGE_CHANNELS evidence or complete visible parent-category overwrite evidence proving MANAGE_CHANNELS for every affected sortable group. Top-level and category groups require guild-level authority. A cross-parent move additionally requires visible exact target metadata plus complete target VIEW_CHANNEL and MANAGE_CHANNELS evidence, as Discord documents independently from destination authority. Validate the exact guild and owner, connector membership, complete bounded roles, arbitrary-width permission bits, unique overwrite targets, supported parents, category capacity, and every response identity before claiming authority. An obfuscated target or anchor remains addressable only by caller-supplied exact ID and privacy-safe topology for a same-parent reorder; an obfuscated target must block a cross-parent move, while an obfuscated anchor may select a destination only when its parent authority is otherwise complete. Never expose or infer hidden metadata.
Bind the normalized request without the raw operation key, its domain-separated hash, verified identities, exact guild and owner, connector membership and permissions, complete roles, complete HTTP evidence and selected mode, complete Gateway layout and baseline revision, every canonical group order, exact target, anchor, source and destination parents, family, capacity, desired source and destination orders, complete normalized payload, overwrite-preservation behavior, impact, risks, warnings, and audit reason into the plan. Any relevant identity, membership, role, overwrite, layout, revision, visibility subset, metadata, order, authority, capacity, reason, target, anchor, placement, or key drift must invalidate review. A verified already-current request must acquire no claim, reserve nothing, journal nothing, subscribe to nothing, request no confirmation, and issue no write.
For a real change, acquire durable claims on the exact target, anchor, applicable parent categories, and guild channel collection before reservation. Atomically reserve and journal, subscribe to layout updates, and synchronously prove that the baseline remains exact before marking mutation as started. Send one non-retried PATCH whose body contains every channel in the reviewed affected groups normalized to sequential positions from zero. A cross-parent payload may add only the exact destination parent_id and literal lock_permissions: false to the target entry; no other parent, permission-sync, flag, or metadata field is allowed. Treat Discord's empty 204 as acceptance only, never as verification. Require a strictly newer complete Gateway layout whose expected topology and every canonical group match, then require one coherent HTTP readback that retains the exact target type, visibility class, and permission overwrites. Do not substitute a timer, one partial Channel Update, only the moved channel, or HTTP evidence without the complete Gateway proof.
A failure proven to occur before mutation, including an arm-time baseline mismatch, or a known non-retriable Discord client rejection before acceptance may settle as failed. Treat transport ambiguity, rate limits, server errors, timeout, continuity loss or malformed dispatches after mutation begins, a newer contradictory layout, a missing complete match, durable receipt finalization failure, or any other indeterminate post-reservation result as uncertain and potentially completed. Permanently spend the key, serialize and quarantine the whole guild channel collection inside direct service instances, and retain the production facade's durable collection claim after uncertainty. Never retry or roll back automatically.
Persist only exact guild, target, anchor, source parent, and destination parent IDs, relative placement, baseline and observed layout revisions, plan digest, operation-key hash, timestamps, fixed verification and outcome values, activity ID, and sanitized error category. Never persist channel names, topics, layout inventories, positions, types, obfuscation state, permission or overwrite evidence, audit reasons, raw operation keys, raw Discord responses, Gateway dispatches, or transport causes.
Canonical source: SECURITY.md
Documentation generated for guildcontrol@0.0.0. Canonical source and edit history remain in the public repository. GuildControl is an independent project and is not affiliated with or endorsed by Discord Inc. Discord is used only to identify the platform that GuildControl connects to.