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: 2 additions & 43 deletions docs-web/architecture/chat-connectors/discord.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,5 @@
# Discord Connector Profile

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.
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.

## 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).
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.
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.

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.
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.

## Provider Profiles

Expand Down
12 changes: 10 additions & 2 deletions docs-web/architecture/chat-connectors/whatsapp.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# WhatsApp Connector Profile

WhatsApp is registered with `managed_bridge` and `webhook` transports. Its module owns the unchanged managed-plugin and webhook setup schemas, Cloud API-shaped inbound normalizer, bridge authentication metadata, outbound URL and credential mapping, configuration verification, and official reference metadata.
WhatsApp implements `managed_bridge`, `webhook`, and direct Meta Cloud API `official_api` transport. The legacy schemas and bridge mappings retain their original meaning; official mode is additive.

The baseline profile has no live test and does not implement `official_api`. Registry construction never contacts WhatsApp.
The official profile fixes Graph traffic to `https://graph.facebook.com/{version}/{phoneNumberId}` and validates both path components before building a request. Outbound messages use the original inbound sender WhatsApp ID as `to`, while `metadata.phone_number_id` remains the channel binding. Replies map the inbound `wamid` to `context.message_id`, and successful response `wamid` values become outbound delivery IDs.

Webhook hooks implement Meta's `hub.mode`, `hub.verify_token`, and `hub.challenge` GET handshake and verify POST `X-Hub-Signature-256` values over exact raw bytes with the app secret. Official authentication explicitly opts out of the shared timestamp requirement because Meta does not send one; all existing profiles retain timestamp enforcement by default. Message and status payloads are discriminated before normalization, and status-only callbacks return an `ignored` acknowledgement without creating delivery or conversation records. Text and media-caption message bodies are supported.

The profile exposes read-only verification of the configured phone-number resource. It uses a bounded timeout and supplies the shared outbound facade with a mode-aware, sanitized classifier for structured Meta error codes, including error envelopes carried by HTTP 200 responses. Response parsing receives the active bridge mode, HTTP status, and headers: only `official_api` interprets Graph envelopes, while managed and webhook modes retain legacy parsing and raw non-2xx error behavior. Returned official errors and verification metadata omit access tokens and recipient values. Normal verification never sends a message; the separate opted-in Meta test-number path owns any future send-based test.

Credentials (`accessToken`, `appSecret`, and `webhookVerifyToken`) remain secret-schema fields and are not exposed through public connection records. Official mode cannot use a custom Graph host or silently fall back to the generic webhook URL.

References: [WhatsApp Cloud API](https://developers.facebook.com/docs/whatsapp/cloud-api), [Meta Webhooks](https://developers.facebook.com/docs/graph-api/webhooks/getting-started), and [Meta's official Postman collection](https://www.postman.com/meta/whatsapp-business-platform/overview).
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; Discord implements `official_api` while preserving its existing webhook schema, and the other profiles retain their existing modes:
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`:

- 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 or provider-native official API.
- Discord: bot/webhook gateway.

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; Discord implements `official_api` while preserving its existing webhook schema, and the other profiles retain their existing modes:
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`:

- 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 or provider-native official API.
- Discord: bot/webhook gateway.

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 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.
- 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.
- 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: 4 additions & 67 deletions docs/settings/chat-connectors/discord.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,9 @@
# Discord Chat Connector

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.
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.

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

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

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).
Official references: [receiving interactions](https://docs.discord.com/developers/interactions/receiving-and-responding) and [message resources](https://docs.discord.com/developers/resources/message).
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 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.
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.

## Providers

Expand Down
Loading
Loading