teams

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package teams implements the Microsoft Teams (Bot Framework) adapter for the pigo chat gateway, speaking the raw connector REST API with no SDK: JWT-validated webhook ingress, typing plus final-only delivery, markdown-subset formatting with UTF-16 chunking, and authenticated attachment download. It plugs into the chat processor via chat.Adapter.

Inbound JWT validation is the trust boundary and is never skippable: New refuses to construct without the app id (the token audience) and secret, and the webhook rejects every request whose Bot Framework token fails the full check chain — RS256 signature against the cached JWKS (with the endorsements filter), issuer, audience, validity window with 5-minute skew, and the serviceUrl claim matching the activity's serviceUrl byte for byte. The endpoint overrides in Options redirect validation at test servers; no configuration disables it.

Index

Constants

View Source
const DefaultIssuer = "https://api.botframework.com"

DefaultIssuer is the issuer of inbound Bot Framework connector tokens.

View Source
const DefaultOpenIDMetadataURL = "https://login.botframework.com/v1/.well-known/openidconfiguration"

DefaultOpenIDMetadataURL is the Bot Framework OpenID metadata document locating the JWKS for inbound token validation.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	// Status is the HTTP status code.
	Status int
	// Code is the error.code string from the error envelope, when present.
	Code string
	// ErrorCode is the Teams-specific numeric errorCode (209 =
	// MessageWritesBlocked), when present.
	ErrorCode int
	// Message is the error message text, when present.
	Message string
	// RetryAfter is the server-requested pause from a Retry-After header,
	// when present (Teams does not guarantee one on 429).
	RetryAfter time.Duration
	// contains filtered or unexported fields
}

APIError is a decoded connector failure.

func (*APIError) Error

func (e *APIError) Error() string

Error implements error.

type Adapter

type Adapter struct {
	// contains filtered or unexported fields
}

Adapter is the Microsoft Teams implementation of chat.Adapter.

func New

func New(opts Options) (*Adapter, error)

New creates a Teams adapter. It refuses to construct without AppID and AppPassword: the app id is the inbound token audience, so inbound validation — the trust boundary — could not run without it.

func (*Adapter) Account

func (a *Adapter) Account() string

Account returns the bot app id, matching the Account set on every normalized message.

func (*Adapter) Download

func (a *Adapter) Download(ctx context.Context, ref chat.AttachmentRef) (io.ReadCloser, string, error)

Download implements chat.Adapter: the attachment contentUrl is fetched directly, with the connector token attached only for known connector hosts (Teams file contentUrls on smba.* need it; sending it anywhere else would leak the token to whoever controls the URL).

ponytail: inline images and connector-served files only; SharePoint attachment URLs need Graph credentials the adapter does not hold.

func (*Adapter) NewDelivery

func (a *Adapter) NewDelivery(key chat.ConversationKey, replyTo string, resumePreviewID string) chat.Delivery

NewDelivery implements chat.Adapter. replyTo is the inbound activity id (the EventID). Teams is final-only, so a recovered preview id is ignored. The serviceUrl comes from the per-conversation store fed by validated inbound activities.

func (*Adapter) Platform

func (a *Adapter) Platform() string

Platform implements chat.Adapter.

func (*Adapter) Webhook

func (a *Adapter) Webhook(publish func(chat.Message) error) http.Handler

Webhook returns the Bot Framework ingress handler. Every POST is authenticated by full inbound JWT validation (403 on any failure) before its body is trusted; message activities are normalized and handed to publish, then the request is acknowledged — ingress never waits on turn processing (publish is the durable enqueue). typing activities are ignored; conversationUpdate and every other type just refresh the stored per-conversation serviceUrl. A publish failure answers 500 so the connector redelivers (the activity id EventID dedupes downstream).

type Options

type Options struct {
	// AppID is the Azure bot application (client) id. Required: it is the
	// outbound OAuth client id, the inbound token audience — validation
	// cannot run without it — and the adapter [Adapter.Account] identity.
	AppID string
	// AppPassword is the app client secret used by the client-credentials
	// grant. Required.
	AppPassword string
	// TenantID selects the single-tenant token endpoint
	// (login.microsoftonline.com/{tenant}); empty means the multi-tenant
	// "botframework.com" endpoint.
	TenantID string
	// TokenURL overrides the OAuth token endpoint (tests).
	TokenURL string
	// OpenIDMetadataURL overrides the OpenID metadata document used to
	// locate the JWKS (tests). Default [DefaultOpenIDMetadataURL].
	OpenIDMetadataURL string
	// Issuer overrides the expected inbound token issuer (tests). Default
	// [DefaultIssuer].
	Issuer string
	// HTTPClient overrides the HTTP client. Default: 30s timeout.
	HTTPClient *http.Client
	// Logger receives non-fatal diagnostics. Optional.
	Logger *slog.Logger
	// TypingInterval is the typing-activity refresh cadence (the indicator
	// is transient). Default 3.5s.
	TypingInterval time.Duration
	// ChunkDelay paces consecutive Finalize chunk sends. Default 350ms.
	ChunkDelay time.Duration
}

Options configures New.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL