Skip to content

Message pins

Keep pin listing read-only, bounded, exact-channel scoped, and on Discord's current timestamp-paginated message-pins endpoint. Do not fall back to the deprecated unpaginated pins route. Validate the page shape, item uniqueness, exact channel and guild identities, pinned booleans, and timestamps before returning normalized messages. Never cache or persist a pin page.

Do not add a pin or unpin shortcut that bypasses the capability gate, exact target-channel allowlist, verified application and bot identities, exact message ID, current pin state, complete role and overwrite evidence, exact private-thread membership, dedicated PIN_MESSAGES permission, process-keyed content-bound plan, signed interactive confirmation, write-aware client approval, final fresh-plan match, atomic one-shot key reservation, pending activity journaling, one non-retried mutation, or exact state and review-snapshot readback. Both desired states remain destructive because unpin removes shared state. If a client cannot support MCP elicitation, keep pin changes unavailable in that client.

Use the thread's validated parent only as its permission-overwrite source; never inherit mutation scope from that parent. Require all message-read prerequisites, including CONNECT for voice and stage channels. Fail closed on partial or malformed evidence and do not treat MANAGE_MESSAGES as an alternative to PIN_MESSAGES.

Bind the review-relevant message snapshot into the opaque process-keyed HMAC so message edits invalidate approval, but never persist message content, attachment metadata, author names, guild or channel names, audit reasons, raw keys, or raw Discord responses. Activity and operation records may contain only exact guild, channel, and message IDs, desired state, plan digest, operation-key hash, timestamps, fixed verification and outcome values, activity ID, and sanitized error category.

Serialize the same exact channel and message target across operation keys inside one process as defense in depth. The production facade also acquires durable exact channel-and-message claims, so connector processes sharing the activity-state root exclude overlapping changes and retain the claims after uncertainty. A known pre-write Discord 4xx may be classified as failed; every transport failure, Discord 5xx response, failed readback after mutation, or otherwise indeterminate outcome is uncertain. Permanently spend every reserved key and never retry or compensate automatically.

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.