4.4 KiB
4.4 KiB
Tasks: enterprise-slack-client
Change ID: enterprise-slack-client
Package: @suaveplan/slack-client
Target path: universal/social/slack-client
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/retry, @suaveplan/crypto
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create
universal/social/slack-client/withsrc/,tests/,src/__benchmarks__/and all feature subdirectories per the layout inproposal.md. - Write
package.jsonat version0.1.0with"type": "module","sideEffects": false, correctexportsmap,dependencies, anddevDependencies. - Write
tsconfig.jsonextending@suaveplan/typescript-config/library.json. - Write
vitest.config.tsusingcreateTestConfig()from@suaveplan/testing/config. - Add
lint,typecheck,test,test:coverage,build,docs:checkscripts.
2. Types + errors
src/types/common.ts—SlackClientOptions,PostMessageOptions,UpdateMessageOptions,ListConversationsOptions,FileUploadOptions,WebhookPayload,SlackMessageResponse,SlackChannel,SlackUser,SlackFile,SlackEvent,SlashCommand,InteractivePayload,SlackBlocks,ActionElement,ContextElement.src/types/common.md(≥200 words, both examples, API reference).src/error-codes.ts—SlackErrorCode(7 codes), metadata, register, eager call.src/types/schemas.ts+schemas.md— Zod schemas.
3. Core modules
src/core/api-caller/—ApiCaller: wrapsfetchcalls tohttps://slack.com/api/; setsAuthorization: Bearerheader; parses JSON response; throwsSLACK_API_ERRORonok:false; throwsSLACK_RATE_LIMITEDon 429 and includesretry_after; wraps calls with@suaveplan/retrycircuit breaker. Tests: success, api error (ok:false), rate-limit (429), circuit breaker opens after 5 failures.src/core/slack-client/—SlackClient: implements all public methods viaApiCaller.listConversationsuses cursor pagination (returnsAsyncGenerator). Tests:postMessagehappy path,updateMessage,deleteMessage,getUserByEmail,uploadFile,postToWebhook.src/blocks/message-builder/—createMessage(text): fluent builder;build()returnsSlackBlocks. Tests: section, divider, image, actions, context; chaining; empty message.src/events/signature-verifier/—verifySlackSignature(body, timestamp, signature, signingSecret, options): HMAC-SHA256 via@suaveplan/crypto; constant-time comparison; reject if|now - ts| > maxAgeSeconds(default 300). Tests: valid, tampered body, expired, missing timestamp.src/events/event-parser/—parseSlackEvent,parseSlashCommand,parseInteractivePayload: Zod validation. Tests: each payload type, invalid payload throws.
4. OTel instrumentation
- Span
slack.api_callwith attributeslack.methodon every API call; counterslack.api_total; histogramslack.api_duration_ms.
5. Property-based tests (tests/property.test.ts)
- Block Kit builder: for arbitrary sequences of
section/divider/imagecalls,build()always returns a validSlackBlocksobject with correcttypefields.
6. Benchmarks (src/__benchmarks__/slack-client.bench.ts)
createMessagebuilder chain (10 sections) 100 000 times.
7. Docs + verify
- One
.mdper implementation file (≥200 words, both examples, API reference). RootREADME.md. bunx turbo lint typecheck test --filter=@suaveplan/slack-client— green.bunx turbo test:coverage --filter=@suaveplan/slack-client— 100%.bun scripts/publish.ts --package @suaveplan/slack-client.- Archive:
openspec/archive/2026-04-24-enterprise-slack-client/.