5.5 KiB
OpenSpec Change: enterprise-slack-client
- Change ID: enterprise-slack-client
- Package:
@suaveplan/slack-client - Category: universal
- Target path:
universal/social/slack-client - Status: IN PROGRESS
- Date: 2026-04-24
- Reference spec:
/mnt/s/web/suaveplan/enterprise/slack-client.md
Summary
Deliver @suaveplan/slack-client on the genesis branch from scratch at enterprise quality. The package provides a generic Slack API client: Web API method wrappers for messaging (chat.postMessage, chat.update, chat.delete), channel management (conversations.*), user info (users.*), file uploads, Block Kit message builder, Incoming Webhooks, Event subscription parsing with signature verification, slash-command payload parsing, interactive component payload handling, and a SlackClient facade. Injectable fetch and crypto; no Slack SDK 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:^) |
SlackError; SLACK.* error codes |
@suaveplan/types (workspace:^) |
LoggerLike, Clock |
@suaveplan/retry (workspace:^) |
Retry + circuit breaker for API calls |
@suaveplan/crypto (workspace:^) |
HMAC-SHA256 request signature verification |
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
SlackClient
class SlackClient {
constructor(options: SlackClientOptions)
// Messaging
postMessage(options: PostMessageOptions): Promise<SlackMessageResponse>
updateMessage(options: UpdateMessageOptions): Promise<SlackMessageResponse>
deleteMessage(channel: string, ts: string): Promise<void>
// Channels
listConversations(options?: ListConversationsOptions): AsyncGenerator<SlackChannel>
getConversationInfo(channel: string): Promise<SlackChannel>
// Users
getUserInfo(userId: string): Promise<SlackUser>
getUserByEmail(email: string): Promise<SlackUser>
// Files
uploadFile(options: FileUploadOptions): Promise<SlackFile>
// Webhooks
postToWebhook(url: string, payload: WebhookPayload): Promise<void>
}
interface SlackClientOptions {
token: string
signingSecret?: string // for event verification
retryOptions?: RetryOptions
fetch?: typeof globalThis.fetch
clock?: Clock
logger?: LoggerLike
}
Block Kit builder
function createMessage(text: string): MessageBuilder
interface MessageBuilder {
section(text: string): MessageBuilder
divider(): MessageBuilder
image(url: string, altText: string): MessageBuilder
actions(...elements: ActionElement[]): MessageBuilder
context(...elements: ContextElement[]): MessageBuilder
build(): SlackBlocks
}
Event handling
function verifySlackSignature(
body: string,
timestamp: string,
signature: string,
signingSecret: string,
options?: { maxAgeSeconds?: number; clock?: Clock }
): boolean
function parseSlackEvent(body: unknown): SlackEvent
function parseSlashCommand(body: unknown): SlashCommand
function parseInteractivePayload(body: unknown): InteractivePayload
Error codes
type SlackErrorCode =
| 'SLACK_AUTH_FAILED'
| 'SLACK_API_ERROR'
| 'SLACK_RATE_LIMITED'
| 'SLACK_SIGNATURE_INVALID'
| 'SLACK_CHANNEL_NOT_FOUND'
| 'SLACK_USER_NOT_FOUND'
| 'SLACK_ABORTED'
Genesis additions
SlackErrorextendsSuaveplanErrorwith seven stable codes.- Zod schemas for
PostMessageOptions,SlackEvent,SlashCommand,InteractivePayload,SlackChannel,SlackUser,SlackFile. - Rate-limit handling — respects
Retry-Afterheader from Slack 429 responses; integrates with@suaveplan/retry. - Circuit breaker — wraps all API calls via
@suaveplan/retrycircuit breaker; opens after 5 consecutive failures. - OTel instrumentation — span
slack.api_callwith attributeslack.method; counterslack.api_total; histogramslack.api_duration_ms. - Property-based tests — Block Kit builder produces valid JSON structures for arbitrary sequences of builder calls.
File layout
universal/social/slack-client/
package.json
tsconfig.json
vitest.config.ts
src/
index.ts
error-codes.ts
constants/
index.ts
types/
common.ts
common.md
core/
slack-client/
slack-client.ts
slack-client.md
slack-client.types.ts
slack-client.test.ts
index.ts
api-caller/
api-caller.ts
api-caller.md
api-caller.test.ts
index.ts
blocks/
message-builder/
message-builder.ts
message-builder.md
message-builder.test.ts
index.ts
events/
event-parser/
event-parser.ts
event-parser.md
event-parser.test.ts
index.ts
signature-verifier/
signature-verifier.ts
signature-verifier.md
signature-verifier.test.ts
index.ts
__benchmarks__/
slack-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, @suaveplan/crypto.