ワンだふる (suteki-bot) 仕様書
apps/suteki-bot (公開名: ワンだふる) の仕様書トップページです。改修着手前にこのページとサブページを必ず読み、変更時は該当ページも合わせて更新してください。
旧称: wonderful-slack-app。
概要
特定の Slack リアクションが付いたら、指定チャンネルに「誰がどのチャンネルでどのリアクションをしたか」を投稿する bot。スラッシュコマンドで Slack ワークスペースごとに監視対象のリアクションと通知先チャンネルを管理する。
ユースケース: 「素振り済み」「投稿しました」など、あらかじめ決めた絵文字をフックに、運営チャンネルへ自動でアナウンスを流す。
実行モード
- Slack Events API (HTTP) で
reaction_addedとスラッシュコマンドを受信する。Socket Mode は廃止 (常駐プロセス不要)。 - ホストは Cloudflare Workers (Worker 名
suteki-bot)。Cloudflare Access の外の公開 Worker に置き、真正性は Slack 署名検証 (HMAC-SHA256, 5 分リプレイ窓) で担保する。 - ストレージは Cloudflare KV (Worker バインディング
TEAM_CONFIG_KV)。 - イベントは即 200 を返し (3 秒 ack)、通知処理は
ctx.waitUntilで応答後に行う。event_idの KV 記録で二重通知を抑止する。
旧構成 (Cloudflare Containers + Bolt Socket Mode) は、5 分おきの cron でコンテナを常時温め続けるためコストがかかり続けることから Worker に移行した。
サブページ
詳細は以下のページに分割しています。
- アーキテクチャ — レイヤー構造、層の責務、データモデル
- コマンドとイベント — スラッシュコマンドと
reaction_addedの処理 - インフラ構成 — Worker / ルーティング / 署名検証 / KV / Slack App 設定
- 運用 / デプロイ — 環境変数、ローカル開発、デプロイ、テスト
- 改修ガイド — 変更時に守るべきルール
設計の不変条件 (Invariants)
これらは「変えてはいけない方針」です。変更が必要な場合はまずこのドキュメントを更新し、レビューで合意してから着手してください。
- クリーンアーキテクチャを崩さない:
domain→application→infrastructureの依存方向を保つ。domainとapplicationは外部 SDK をインポートしない。新しい外部依存は port を切ってからinfrastructureで実装する。 - Slack 署名検証を必ず通す:
/slack/eventsと/slack/commandsは公開エンドポイントなので、署名検証 (verify-signature.ts) を通らないリクエストを処理してはいけない。検証を外したり、検証前に副作用を起こす改修は禁止。 - 3 秒以内に ack する: Slack Events API は 3 秒以内に 200 が返らないとリトライする。イベントの通知処理は
ctx.waitUntilで応答後に行い、fetch ハンドラに同期の重い処理を足さない。リトライによる二重通知はevent:{event_id}キーの KV 記録で抑止する。 - プライベートチャンネルでのリアクションは絶対に通知しない:
notify-reaction.tsのchannel?.isPrivateガードはプライバシー上の不変条件。SlackGateway.fetchChannelInfoは{ name, isPrivate }を返す。isPrivateチェックを外す改修は禁止。 - 認証はアプリ層に置かない: ワークスペース単位の設定は
TeamConfigに閉じ、追加の認証/認可ロジックを足さない。署名検証は「認証」ではなくリクエスト検証。 - TypeScript の相対 import に拡張子を付けない: 本リポジトリは
moduleResolution: "bundler"統一。./foo.jsではなく./foo。