Skip to content

Scheduled events

Keep scheduled-event inventory behind its own audit toggle and exact guild allowlist. Project Discord responses immediately to bounded event metadata, exact identities, optional aggregate subscriber counts, and complete entity-specific permission evidence. Ordinary inventory and exact-event reads must never return subscriber identities, creator profiles, cover URLs or hashes, embedded objects, or unknown raw fields. Require complete guild, bot-member, role, channel, permission, and event evidence before returning a read or plan.

Keep scheduled-event subscriber identities behind an additional opt-in that inherits the exact event guild scope. Resolve the exact event and complete entity-specific read evidence before calling the user endpoint. Force with_member=false, accept only bounded forward pagination, and project each raw row inside the REST client to an exact user ID plus bot flag. Reject member expansion, mismatched event IDs, invalid or duplicate users, and non-ascending pages. Never return or persist usernames, display names, avatars, nicknames, roles, join dates, member objects, profile fields, or raw payloads.

Keep every create, metadata update, lifecycle transition, and deletion behind the independent change toggle, process-keyed planning, signed interactive confirmation, write-aware host approval, final fresh-plan match, atomic one-shot operation-key reservation, pending content-free activity, one non-retried mutation, and exact state or absence readback. Do not add an immediate-call path, bulk mutation, fuzzy event lookup, subscriber profile enumeration, subscriber mutation, retry, rollback, or reconciliation.

Enforce Discord's exact entity-specific permission rules. Creation requires CREATE_EVENTS plus the documented voice or stage channel permissions. Updating, transitioning, or deleting requires MANAGE_EVENTS, or exact connector-bot ownership together with CREATE_EVENTS, plus the current entity's channel permissions. A hosting move must also prove the complete creation permissions at the destination. Missing creator evidence cannot establish ownership, and ADMINISTRATOR must remain a warning rather than a recommended setup.

Normalize exact action-specific fields, canonical timestamps, future starts, end-after-start ordering, external hosting requirements, documented lifecycle transitions, and only Discord-supported recurrence shapes. Never synthesize server-controlled recurrence count, end, or year-day fields. A recurring start-time change must explicitly replace or remove recurrence. Keep active-event metadata changes limited to fields Discord safely permits, and reject metadata changes to terminal events.

Cover input must remain local-file-only and single-file. Never accept a remote URL, Discord CDN reference, data URL, base64 payload, arbitrary byte field, stream, directory, multiple files, or runtime-configurable Discord origin. Accept only bounded JPEG or non-animated PNG content under a dedicated root. Reject path escapes, symlinks, hardlinks, foreign ownership, unstable reads, unsupported or animated formats, invalid dimensions, and files above the fixed ceiling before reservation. Upload only the reviewed byte snapshot bound into the fresh plan.

Bind the normalized request, verified identities, exact guild and event state, current and destination authority, relevant role and channel evidence, visible creation inventory, privacy projection, local cover state, warnings, and domain-separated operation-key hash into the plan. Exclude the raw operation key from plan material, signed request state, records, results, and errors. A reserved key remains spent after every outcome, including known failure, local recording failure, or uncertainty.

Treat a known pre-write Discord client error as failed. Treat transport errors, malformed mutation responses, Discord server errors, and failures after a mutation or during exact readback as uncertain and potentially completed. Cover verification can prove reviewed bytes were sent and a cover is present afterward, but must not claim byte equality because Discord does not return stored image bytes. Never retry, compensate, or roll back automatically.

Serialize scheduled-event changes per guild inside one process as defense in depth. The production facade also acquires a durable exact guild scheduled-events collection claim, so connector processes sharing the activity-state root exclude overlapping changes and retain the claim after uncertainty. Never persist event names, descriptions, locations, recurrence fields, subscriber counts or user IDs, role names, local paths, file metadata, image bytes, content digests, audit reasons, raw operation keys, permission evidence, or raw Discord responses. Activity and operation records may contain only exact guild and event IDs, entity type, action and transition target, plan digest, operation-key hash, timestamps, fixed verification and outcome values, activity ID, and sanitized error category.

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.