# OpenSpec Change: enterprise-telegram-client - **Change ID**: enterprise-telegram-client - **Package**: `@suaveplan/telegram-client` - **Category**: universal - **Target path**: `universal/social/telegram-client` - **Status**: IN PROGRESS - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/telegram-client.md` --- ## Summary Deliver `@suaveplan/telegram-client` on the genesis branch from scratch at enterprise quality. The package provides a generic Telegram Bot API client: `sendMessage`, `sendPhoto`, `sendDocument`, `sendAudio`, `sendVideo`, `editMessageText`, `deleteMessage`, `answerCallbackQuery`, `answerInlineQuery`, `setWebhook`/`deleteWebhook`, `getUpdates` long-poll loop, inline keyboard builder, reply keyboard builder, and a `TelegramBot` facade. Injectable fetch; no `node-telegram-bot-api` dependency. Genesis adds structured errors, Zod schemas, OTel instrumentation, retry with circuit breaker, and `AbortSignal` cancellation. --- ## Current-state audit (genesis) The package does not exist on genesis yet — this is a fresh build. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/error` (`workspace:^`) | `TelegramError`; `TELEGRAM.*` error codes | | `@suaveplan/types` (`workspace:^`) | `LoggerLike`, `Clock` | | `@suaveplan/retry` (`workspace:^`) | Retry + circuit breaker for API calls | | `zod` (`catalog:forms`) | Schema validation | | `@opentelemetry/api` (`catalog:observability`) | Spans + counters | Dev deps: `vitest`, `@vitest/coverage-istanbul`, `fast-check` (all `catalog:testing`). --- ## Public API surface ### `TelegramBot` ```ts class TelegramBot { constructor(options: TelegramBotOptions) // Messaging sendMessage(chatId: ChatId, text: string, options?: SendMessageOptions): Promise sendPhoto(chatId: ChatId, photo: string | Uint8Array, options?: SendMediaOptions): Promise sendDocument(chatId: ChatId, document: string | Uint8Array, options?: SendMediaOptions): Promise editMessageText(chatId: ChatId, messageId: number, text: string, options?: EditOptions): Promise deleteMessage(chatId: ChatId, messageId: number): Promise forwardMessage(toChatId: ChatId, fromChatId: ChatId, messageId: number): Promise // Callbacks and inline answerCallbackQuery(callbackQueryId: string, options?: AnswerCallbackOptions): Promise answerInlineQuery(inlineQueryId: string, results: InlineQueryResult[]): Promise // Webhooks and polling setWebhook(url: string, options?: WebhookOptions): Promise deleteWebhook(): Promise getUpdates(options?: GetUpdatesOptions): AsyncGenerator // Bot info getMe(): Promise } type ChatId = number | string interface TelegramBotOptions { token: string retryOptions?: RetryOptions fetch?: typeof globalThis.fetch clock?: Clock logger?: LoggerLike } ``` ### Keyboard builders ```ts function inlineKeyboard(rows: InlineKeyboardButton[][]): InlineKeyboardMarkup function replyKeyboard(rows: KeyboardButton[][], options?: ReplyKeyboardOptions): ReplyKeyboardMarkup function removeKeyboard(): ReplyKeyboardRemove ``` ### Error codes ```ts type TelegramErrorCode = | 'TELEGRAM_AUTH_FAILED' | 'TELEGRAM_API_ERROR' | 'TELEGRAM_RATE_LIMITED' | 'TELEGRAM_CHAT_NOT_FOUND' | 'TELEGRAM_MESSAGE_NOT_FOUND' | 'TELEGRAM_WEBHOOK_FAILED' | 'TELEGRAM_ABORTED' ``` --- ## Genesis additions 1. **`TelegramError`** extends `SuaveplanError` with seven stable codes. 2. **Zod schemas** for `TelegramMessage`, `TelegramUpdate`, `TelegramUser`, `SendMessageOptions`, `InlineKeyboardMarkup`, `ReplyKeyboardMarkup`, `InlineQueryResult`. 3. **Long-poll loop** — `getUpdates` returns an `AsyncGenerator` that manages offset tracking and exits cleanly on `AbortSignal`. 4. **Rate-limit handling** — Telegram returns 429 with `retry_after`; the client waits the prescribed delay before retrying. 5. **OTel instrumentation** — span `telegram.api_call` with attribute `telegram.method`; counter `telegram.api_total`; histogram `telegram.api_duration_ms`. 6. **Property-based tests** — keyboard builder produces valid nested JSON for arbitrary row/button configurations. --- ## File layout ```text universal/social/telegram-client/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts constants/ index.ts types/ common.ts common.md core/ telegram-bot/ telegram-bot.ts telegram-bot.md telegram-bot.types.ts telegram-bot.test.ts index.ts api-caller/ api-caller.ts api-caller.md api-caller.test.ts index.ts update-poller/ update-poller.ts update-poller.md update-poller.test.ts index.ts keyboards/ keyboard-builder/ keyboard-builder.ts keyboard-builder.md keyboard-builder.test.ts index.ts __benchmarks__/ telegram-client.bench.ts tests/ integration.test.ts property.test.ts ``` --- ## Impact **Downstream consumers**: `@suaveplan/message-bridge`, `@suaveplan/notification-channel`. **Workspace dep prerequisites**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/retry`.