Skip to content

インフラ構成

ワンだふる (apps/suteki-bot) のホスティングと外部連携。

Worker 構成

単一の Cloudflare Worker (suteki-bot) が Slack からの HTTP リクエストを直接受ける。常駐プロセス・コンテナ・cron は存在しない。

ルートメソッド役割
/slack/eventsPOSTEvents API (reaction_added, url_verification)
/slack/commandsPOSTスラッシュコマンド 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 v2deleted_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 — ワークスペースドメイン取得