Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions docs-web/architecture/chat-connectors/discord.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,46 @@
# Discord Connector Profile

Discord is registered only with the existing `webhook` bot/gateway transport. Its module owns the unchanged setup schema, message normalizer, authentication headers and signature bases, outbound gateway mapping, response parsing, verification metadata, and session requirement.
Discord has two independently selected transports. The existing `webhook` mode preserves custom bot/gateway URLs and stored connection compatibility. The provider-native `official_api` mode owns Discord HTTP interaction authentication, Gateway v10 message delivery, REST replies, and read-only credential verification.

The baseline profile has no live test and does not advertise managed, native, or `official_api` modes. Unsupported combinations fail before network or process execution.
## Official configuration and trust boundary

The official setup requires an application ID, the application's hexadecimal Ed25519 public key, a Gateway intents bitfield, and a write-only bot token. The default bitfield is `37377`: `GUILDS`, `GUILD_MESSAGES`, `DIRECT_MESSAGES`, and privileged `MESSAGE_CONTENT`. Operators must enable `MESSAGE_CONTENT` in the Discord Developer Portal to receive ordinary message bodies.

Official REST requests are pinned to `https://discord.com/api/v10`. Gateway and resume URLs must use secure Discord-owned `discord.gg` hosts. Values retained for legacy webhook connections cannot redirect official traffic. Bot tokens, interaction tokens, and authorization headers are excluded from persisted Gateway state and delivery metadata.

## Interaction ingress

The profile validates `X-Signature-Ed25519` against `X-Signature-Timestamp` plus the exact raw body before JSON parsing. Missing or malformed headers, malformed keys, stale timestamps, invalid signatures, malformed JSON, and unsupported interaction shapes produce deterministic classified failures. Authenticated type-1 validation requests receive the required JSON PONG response.

`ChatProviderIngressSecurity` invokes the optional provider-native hook before generic bearer/HMAC handling. The production ingress route returns an immediate authenticated handshake response when present and otherwise continues into the existing ingress service.

Application command, component, and modal payloads normalize into stable external channel, sender, interaction-message, and Discord thread identities. Gateway `MESSAGE_CREATE` payloads use the same normalized contract.

## Gateway state machine

`DiscordGatewaySession` is transport- and persistence-neutral. It receives injected WebSocket, timer, delay, and session-store boundaries so unit tests are completely offline.

The state machine implements:

- `Identify` and `Resume` payloads for Gateway v10;
- latest dispatch sequence tracking;
- first-heartbeat jitter, recurring heartbeats, ACK tracking, and immediate reconnect after a missed ACK;
- persistence of only `sessionId`, Discord resume URL, sequence, and bot user ID;
- resume after recoverable closes and re-identify after invalid sequence, timed-out session, or non-resumable invalid-session responses;
- bounded exponential reconnect backoff;
- terminal classifications for invalid auth, invalid intents, missing privileged intent access, shard errors, and unsupported Gateway versions;
- cancellation and clean shutdown that stop timers, close the socket, and prevent reconnects.

The bot user ID from `READY` suppresses the connector's own `MESSAGE_CREATE` events without suppressing messages from unrelated bot accounts.

## REST replies and verification

Message creation disables all automatic mentions with `allowed_mentions.parse: []`, supplies a stable delivery nonce with `enforce_nonce`, preserves reply references, and accepts only snowflake message IDs from successful responses. Route/global reset headers and `Retry-After` are honored with one bounded immediate 429 retry; further rate limits are returned to the outer delivery scheduler.

The configured outbound adapter caches the profile's official executor, preserving Discord rate-limit state across production deliveries. Profiles without an executor, including Discord `webhook`, retain the generic HTTP or command path.

Credential verification performs only `GET /users/@me`. Typed results distinguish invalid authentication, missing permissions, rate limiting, timeout, cancellation, ambiguous network outcomes, provider unavailability, and invalid responses without retaining token-bearing messages.

The profile remains side-effect free when the registry is constructed. Network and Gateway work begins only when the corresponding runtime client or session is explicitly started.

References: [Gateway](https://docs.discord.com/developers/events/gateway), [Gateway events](https://docs.discord.com/developers/events/gateway-events), [Interactions](https://docs.discord.com/developers/interactions/overview), [Messages](https://docs.discord.com/developers/resources/message), and [Rate limits](https://docs.discord.com/developers/topics/rate-limits).
2 changes: 1 addition & 1 deletion docs-web/architecture/chat-connectors/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Code UX registers one typed, independently editable profile for each external ch

The registry is static and side-effect free. Network requests and native command execution remain in service-layer facades. Lookup fails closed when a provider or provider/mode combination is not registered.

The additive `official_api` mode is available to future profiles without changing the persisted meaning of `managed_bridge`, `webhook`, or `native_bridge`. Baseline profiles advertise only implemented modes.
Discord implements the additive `official_api` mode without changing the persisted meaning of `managed_bridge`, `webhook`, or `native_bridge`. Other profiles advertise only the modes they implement.

## Provider Profiles

Expand Down
4 changes: 2 additions & 2 deletions docs-web/architecture/external-chat-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ Supported providers:
- `microsoft-teams`
- `discord`

The bridge-mode type includes `managed_bridge`, `webhook`, `native_bridge`, and the additive `official_api` value. Profiles advertise only implemented modes; baseline profiles preserve the existing schemas below and do not yet advertise `official_api`:
The bridge-mode type includes `managed_bridge`, `webhook`, `native_bridge`, and the additive `official_api` value. Profiles advertise only implemented modes; Discord implements `official_api` while preserving its existing webhook schema, and the other profiles retain their existing modes:

- WhatsApp: managed bridge or webhook.
- iMessage: managed bridge or macOS native bridge command.
- Telegram: managed bridge or bot webhook.
- Slack: managed bridge or Events webhook.
- Microsoft Teams: managed bridge or bot webhook.
- Discord: bot/webhook gateway.
- Discord: bot/webhook gateway or provider-native official API.

Public records expose redacted credential metadata only. Runtime code that needs secrets must call the explicit internal repository read path.

Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/external-chat-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ Supported providers:
- `microsoft-teams`
- `discord`

The bridge-mode type includes `managed_bridge`, `webhook`, `native_bridge`, and the additive `official_api` value. A profile advertises only modes it implements; the baseline profiles preserve the existing schemas below and do not yet advertise `official_api`:
The bridge-mode type includes `managed_bridge`, `webhook`, `native_bridge`, and the additive `official_api` value. A profile advertises only modes it implements; Discord implements `official_api` while preserving its existing webhook schema, and the other profiles retain their existing modes:

- WhatsApp: managed bridge or webhook.
- iMessage: managed bridge or macOS native bridge command.
- Telegram: managed bridge or bot webhook.
- Slack: managed bridge or Events webhook.
- Microsoft Teams: managed bridge or bot webhook.
- Discord: bot/webhook gateway.
- Discord: bot/webhook gateway or provider-native official API.

Public records expose redacted credential metadata only. Runtime code that needs secrets must call the explicit internal repository read path.

Expand Down
2 changes: 1 addition & 1 deletion docs/mcp/tools-and-contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ For preview calls:

For external chat provider calls:
- `manage_chat_providers` supports `list_provider_definitions`, `list_connections`, `get_connection`, `create_connection`, `update_connection`, `delete_connection`, `list_channel_bindings`, `create_channel_binding`, `update_channel_binding`, `delete_channel_binding`, and `list_outbound_deliveries`.
- Supported provider kinds are `whatsapp`, `imessage`, `telegram`, `slack`, `microsoft-teams`, and `discord`, delivered through the implemented `managed_bridge`, `webhook`, or `native_bridge` bridge contracts. The tool does not claim direct official API integration with those providers.
- Supported provider kinds are `whatsapp`, `imessage`, `telegram`, `slack`, `microsoft-teams`, and `discord`, delivered through their implemented `managed_bridge`, `webhook`, `native_bridge`, or provider-specific `official_api` contracts. Discord implements direct official API transport; unsupported provider/mode combinations fail validation.
- Connection responses return redacted credential metadata and generated ingress URL guidance; raw `secrets` are not exposed in success responses, validation errors, or approval envelopes.
- `delete_connection` and `delete_channel_binding` require approval confirmation.
- `update_connection` requires a one-use approval handshake before replacing a non-empty `secrets` payload. The preflight response is bound to a redacted payload plus secret hash and does not echo secret values.
Expand Down
71 changes: 67 additions & 4 deletions docs/settings/chat-connectors/discord.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,72 @@
# Discord Chat Connector

The baseline Discord profile supports only `webhook`, matching the existing bot/webhook gateway contract. It normalizes Discord message payloads and deliberately does not advertise managed, native, or direct official API delivery.
Discord supports the existing `webhook` bridge and a provider-native `official_api` mode. Existing stored webhook connections keep their current setup and routing behavior; changing to `official_api` is explicit.

Setup remains compatible with stored connections: optional `gatewayUrl` and `applicationId`, required `botToken`, and optional `webhookSecret`. A bot or gateway session owns provider event delivery.
## Setup modes

Live provider testing is not implemented by this baseline profile.
### Official API

Official references: [receiving interactions](https://docs.discord.com/developers/interactions/receiving-and-responding) and [message resources](https://docs.discord.com/developers/resources/message).
Configure these values from the Discord Developer Portal:

- **Application ID**: the Discord application snowflake.
- **Interactions public key**: the 32-byte hexadecimal Ed25519 public key. This is public configuration, not a bot credential.
- **Gateway intents bitfield**: defaults to `37377` (`GUILDS`, `GUILD_MESSAGES`, `DIRECT_MESSAGES`, and `MESSAGE_CONTENT`).
- **Bot token**: a required write-only secret. Code UX redacts it from connection responses and never stores it in Gateway session state or delivery metadata.

`MESSAGE_CONTENT` is a privileged Gateway intent. Enable it on the application's **Bot** page in the Developer Portal before starting the connector. Without it, ordinary `MESSAGE_CREATE` events may omit `content`; Discord can close the Gateway with code `4014` when a privileged intent is requested without access.

The official connector controls its network destinations. REST calls use only `https://discord.com/api/v10`, and Gateway connections use Discord-owned `wss://*.discord.gg` hosts. A saved `gatewayUrl`, webhook URL, bridge URL, or an untrusted resume URL cannot replace those origins in `official_api` mode.

### Webhook compatibility

The `webhook` mode retains the stored bot/webhook gateway contract:

- optional `gatewayUrl` and `applicationId`
- required `botToken`
- optional `webhookSecret`

Outbound requests continue to use the configured custom gateway URL and the shared legacy bridge authentication and response parsing behavior.

## HTTP interactions

Discord signs each HTTP interaction with `X-Signature-Ed25519` and `X-Signature-Timestamp`. Code UX verifies the signature over the timestamp concatenated with the exact raw request body, checks a five-minute freshness window, and rejects missing, malformed, stale, or mismatched authentication with a deterministic `400` or `401` result. Parsing or reserializing JSON before signature verification is not safe because it changes the signed bytes.

An authenticated interaction with `type: 1` receives HTTP `200`, JSON content type, and `{ "type": 1 }` as required by Discord's endpoint validation. Supported command, component, and modal interactions normalize to stable Discord channel, sender, interaction-message, and thread identities.

The normal chat-provider ingress route invokes this provider-native verification before acknowledgement or message routing. PING requests stop at the handshake response; other authenticated interactions continue through the existing binding, idempotency, and conversation delivery path.

## Gateway delivery

Official message delivery uses Gateway v10 with JSON encoding. A connection:

1. waits for `Hello`, starts the first heartbeat at Discord's randomized jitter offset, and sends `Identify`;
2. records every dispatch sequence and persists only `session_id`, `resume_gateway_url`, sequence, and the bot user ID;
3. sends `Resume` after resumable disconnects and falls back to `Identify` after invalid or expired sessions;
4. reconnects when a heartbeat is not acknowledged, using bounded exponential backoff;
5. stops all heartbeat and reconnect work on cancellation or shutdown.

Only `MESSAGE_CREATE` dispatches are normalized for chat ingress. Messages authored by the connected bot user are ignored to prevent reply loops.

## Replies and rate limits

Replies use `POST /channels/{channel.id}/messages` on API v10. Code UX always sends `allowed_mentions.parse: []`, a stable delivery nonce with `enforce_nonce: true`, and a Discord `message_reference` when replying to an inbound message. Returned message IDs must be valid snowflakes before they are recorded.

The client tracks route and global rate-limit headers, waits for Discord's `Retry-After` or reset interval, and performs at most one immediate 429 retry. Persistent rate limiting returns a retryable classified failure to the shared delivery scheduler rather than creating an internal retry storm.

The shared outbound service retains one Discord executor for official deliveries, so rate-limit state is reused across attempts. The custom `webhook` mode continues through the legacy configured-URL adapter.

## Credential verification and failures

Credential verification is read-only and calls only `GET https://discord.com/api/v10/users/@me`. Results distinguish:

- invalid bot authentication (`401`)
- missing channel permissions (`403` during delivery)
- rate limiting (`429`)
- request timeout or cancellation
- ambiguous network outcome
- temporary provider failure and invalid provider responses
- invalid Gateway intents and unavailable privileged intents

Errors and verification results use bounded, token-free messages. Live credential tests are separate from unit tests; deterministic unit fixtures use mocked HTTP and Gateway transports and never contact Discord.

Official references: [Gateway](https://docs.discord.com/developers/events/gateway), [Gateway events](https://docs.discord.com/developers/events/gateway-events), [Interactions](https://docs.discord.com/developers/interactions/overview), [Messages](https://docs.discord.com/developers/resources/message), and [Rate limits](https://docs.discord.com/developers/topics/rate-limits).
2 changes: 1 addition & 1 deletion docs/settings/chat-connectors/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Each supported external chat connector has an independently editable runtime profile. A profile owns its setup schema, implemented transport modes, ingress authentication and normalization, conversation identity rules, outbound mapping, verification capabilities, session requirements, official references, and lifecycle metadata.

The `official_api` bridge-mode type is reserved for additive provider implementations. A connector page lists only modes its baseline profile currently implements; existing `managed_bridge`, `webhook`, and `native_bridge` records keep their established meaning.
The additive `official_api` bridge mode is implemented by Discord; other connector pages list only the modes their profiles implement. Existing `managed_bridge`, `webhook`, and `native_bridge` records keep their established meaning.

## Providers

Expand Down
6 changes: 3 additions & 3 deletions docs/settings/chat-provider-integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ Code UX supports external chat channels through the bridge contracts implemented
| `telegram` | managed bridge, bot webhook |
| `slack` | managed bridge, Events webhook |
| `microsoft-teams` | managed bridge, bot webhook |
| `discord` | bot/webhook gateway |
| `discord` | bot/webhook gateway or official API |

These connector labels describe the normalized payloads Code UX can accept and the bridge setup schemas it exposes. Code UX does not call WhatsApp, iMessage, Telegram, Slack, Microsoft Teams, or Discord APIs directly. A managed bridge, webhook gateway, or native command owns provider-specific API interaction.
These connector labels describe the normalized payloads Code UX can accept and the bridge setup schemas it exposes. Discord's `official_api` profile calls Discord directly; the other providers continue to use a managed bridge, webhook gateway, or native command for provider-specific API interaction.

The contract also defines an additive `official_api` mode for future direct connectors. None of the baseline profiles advertise it, so unsupported provider/mode combinations fail validation without changing existing stored bridge records. Provider-specific baseline details are listed in [Chat Connector Profiles](./chat-connectors/index.md).
The contract also defines an additive `official_api` mode, currently implemented by Discord. Unsupported provider/mode combinations still fail validation without changing existing stored bridge records. Provider-specific details are listed in [Chat Connector Profiles](./chat-connectors/index.md).

Bridge modes:

Expand Down
Loading
Loading