インフラ構成
ワンだふる (apps/suteki-bot) のホスティングと外部連携。
Worker 構成
単一の Cloudflare Worker (suteki-bot) が Slack からの HTTP リクエストを直接受ける。常駐プロセス・コンテナ・cron は存在しない。
| ルート | メソッド | 役割 |
|---|---|---|
/slack/events | POST | Events API (reaction_added, url_verification) |
/slack/commands | POST | スラッシュコマンド 3 種 (payload の command でディスパッチ) |
上記以外のパス / メソッドは 404。
この Worker は Cloudflare Access の外 に公開する (Slack からの受信に公開 URL が必要なため)。Access の bypass 設定は不要。
Slack 署名検証
公開エンドポイントの真正性は Slack 署名 (src/verify-signature.ts) で担保する。
x-slack-signature/x-slack-request-timestampヘッダと raw body から HMAC-SHA256 で検証。- タイムスタンプが 5 分以上ずれたリクエストは拒否 (リプレイ防止)。
- 検証は両ルート共通で、検証前に副作用を起こさない。
3 秒 ack と二重通知の抑止
- Events API は 3 秒以内に 200 が返らないとリトライする (at-least-once 配送)。
/slack/eventsは即 200 を返し、通知処理はctx.waitUntilで応答後に実行する。 - リトライによる二重通知は
event:{event_id}キーを KV に TTL 1 時間で記録して抑止する。KV は結果整合なのでごく短い間隔の重複は理論上すり抜けうるが、実用上は十分。 - スラッシュコマンドは KV の読み書き程度なので同期処理し、HTTP レスポンスをそのままコマンド応答にする。
KV アクセス
wrangler.toml の KV バインディング TEAM_CONFIG_KV を使う。旧 Container 構成では REST API (KvRestClient) 経由だったが、Worker 内から直接バインディングを叩けるため REST と API トークンは不要になった。namespace は旧構成と同じものを指しており、TeamConfig データはそのまま引き継がれている。
Durable Object の削除マイグレーション
旧構成の Container 用 Durable Object (SutekiBotContainer) は wrangler.toml の [[migrations]] tag v2 の deleted_classes で削除済み。migrations 履歴 (v1 → v2) は既存 Worker への上書きデプロイに必要なので消さないこと。
Slack App 設定
- Socket Mode: 無効
- Event Subscriptions: 有効。Request URL は Worker の
https://<worker-url>/slack/events。Subscribe to bot events:reaction_added - Slash Commands:
/reaction-track,/reaction-untrack,/reaction-list— それぞれの Request URL を Worker のhttps://<worker-url>/slack/commandsに向ける - App-level Token: 不要 (Socket Mode 廃止に伴い削除可)
- Bot Token Scopes:
chat:write— 通知投稿commands— スラッシュコマンドreactions:read— リアクションイベント受信users:read— ユーザー名取得channels:read— チャンネル名取得team:read— ワークスペースドメイン取得