Skip to content

Authenticated widget settings

Keep widget-settings inspection behind its own audit toggle and exact guild allowlist. The allowlist must remain a subset of any configured read-guild scope. Use only Discord's authenticated guild widget-settings endpoint. Do not call, proxy, cache, or expose the anonymous widget JSON or widget-image routes because their public guild, channel, presence-oriented, and invite data is outside the administrative evidence boundary.

Require verified application and bot identities, an exact guild and owner, exact connector membership, complete bounded roles, direct guild channels and overwrites, effective permissions, and a strict authenticated settings object before returning an audit or plan. Use optional guild-object widget fields only as a contradiction-detecting cross-check. Omit channel names, member and presence data, invites, raw payloads, and unknown-field values. Treat unknown settings fields, unknown permission bits, malformed or incomplete inventories, missing references, cross-check contradictions, and unsupported or hidden selected channels as blockers for change.

Keep replacement behind a second toggle and the same exact guild scope. Require complete MANAGE_GUILD authority unless the connector is the exact guild owner. A selected channel must be one exact direct text, voice, announcement, Stage, forum, or media channel with complete permission evidence and effective VIEW_CHANNEL for @everyone. Report effective CREATE_INSTANT_INVITE for @everyone as public-exposure evidence without treating it as connector mutation authority. Do not infer eligibility from a parent allowlist, connector-only visibility, a name, or a partial channel object.

Keep public exposure behind an independent action-sensitive toggle. Require it for every real write whose desired state is enabled and for every real write that selects a different non-null channel, including a latent target while disabled. Do not require it for an exact no-op, a reviewed disable retaining the current channel, or clearing the channel while disabled. This exception must not become a general write bypass: audit scope, change scope, complete evidence, planning, confirmation, approval, freshness, reservation, journaling, and readback remain mandatory.

Treat every request as one exact complete desired state containing the enabled boolean and nullable channel ID. Do not add an immediate-call, partial-update, fuzzy-channel, public-widget read, widget-image, invite-creation, member-presence, retry, rollback, or compensating shortcut. Preserve every gate: verified identities, exact policy, complete evidence, strict full-state normalization, process-keyed plan binding, signed interactive confirmation, write-aware client approval, final fresh-plan match, atomic one-shot operation-key reservation, pending content-free activity, one non-retried PATCH with an encoded audit-log reason, strict authoritative-response validation, and a complete fresh authenticated readback. A client without MCP elicitation must not execute widget-settings replacement.

The plan digest must bind the normalized complete request, operation-key hash, verified identities, guild owner, connector membership and authority, complete roles, channels and overwrites, effective connector and @everyone permissions, authoritative current settings, optional guild cross-check, desired state, diff, action-sensitive exposure authorization, privacy projection, risks, warnings, and verification boundary. Any identity, permission, channel, overwrite, state, cross-check, desired value, audit reason, exposure policy, or operation-key change must invalidate the review. An already-current request must return without exposure authorization, confirmation, reservation, activity, or mutation.

A definite Discord client refusal may be classified as failed. Treat transport failure, Discord server failure, malformed success, unsafe or mismatched authoritative response, failed full readback, failed receipt finalization, or any otherwise indeterminate post-reservation state as uncertain and potentially completed. Spend every reserved key after every outcome, retain a permanent same-guild uncertainty barrier inside the service instance, and never retry, roll back, or compensate automatically. Keep same-guild serialization inside each process as defense in depth. The production facade also acquires a durable exact guild widget-settings collection claim, so connector processes sharing the activity-state root exclude overlapping changes and retain the claim after uncertainty.

Widget-settings activity and operation records may contain only the exact guild ID, plan digest, operation-key hash, timestamps, fixed verification and outcome values, activity ID, and sanitized error category. Never persist enabled state, selected channel IDs, guild or channel names, permission evidence, exposure details, audit reasons, raw operation keys, raw Discord responses, or transport causes. Enabling the widget makes the Server Profile public outside the guild and can permit anonymous invite generation. Disabling it does not restore Private Profile. Keep a fresh non-member review after enabling and manual Private Profile inspection and restoration after disabling as explicit operator steps, and never claim that authenticated API readback verifies either external result.

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.