SavvyBot Phase 1-2
基盤構築とセキュリティ強化
GAS MVPからSupabase Edge Functionsへの移行完了。HMAC-SHA256署名検証の実装、Result型によるエラーハンドリング、CI/CDパイプライン構築を完了し、堅牢なインフラ基盤を確立。
Technologies Used
SavvyBot Phase 1-2 ― 基盤構築とセキュリティ強化
Phase 1: GAS での MVP(完了 - 2023年3月)
実装内容
基本機能:
- LINE Messaging API と OpenAI API の基本連携
- 簡易的なチャットボット機能の実装
- Google Apps Script (GAS) による迅速なプロトタイピング
課題と学び
セキュリティ上の課題:
- シークレット(APIキー)の管理が困難
- 署名検証の実装が不十分
- スクリプトプロパティでの環境変数管理の脆弱性
パフォーマンス上の課題:
- GASの実行時間制限(最大6分)
- コールドスタート時の遅延
- スケーラビリティの限界
開発効率の課題:
- ローカル開発環境の不足
- TypeScript型チェックなし
- テストの困難さ
これらの課題から、本格的なプロダクション環境への移行の必要性を認識しました。
Phase 2: Supabase Edge Functions への移行(完了 - 2025年10月)
達成事項
- ✅ HMAC-SHA256 署名検証の実装(セキュリティ強化)
- ✅ Result 型によるエラーハンドリング
- ✅ 構造化ログによる可観測性の確保
- ✅ GitHub Actions による CI/CD パイプライン構築
- ✅ 実機テストでの動作確認完了
技術的成果
1. セキュリティ強化 - HMAC-SHA256署名検証
課題: 署名検証エラー(403 Forbidden)の解決
LINE Messaging APIからのWebhook呼び出しを検証するため、HMAC-SHA256署名検証を実装しました。当初、署名検証が常に失敗する問題に直面しましたが、以下の3つの根本原因を特定して解決しました。
実装内容:
// lib/security.ts
import { createHmac } from 'node:crypto';
export async function verifySignature(
body: string,
signature: string,
channelSecret: string
): Promise<boolean> {
// HMAC-SHA256ハッシュを生成
const hash = createHmac('sha256', channelSecret)
.update(body)
.digest('base64');
// 定数時間比較(タイミング攻撃対策)
return timingSafeEqual(
Buffer.from(signature),
Buffer.from(hash)
);
}
解決したバグ:
- 非同期Web Crypto APIの誤使用: Node.js の
cryptoモジュールを使用することで解決 - 定数時間比較の欠如: タイミング攻撃を防ぐため
timingSafeEqual()を実装 - 診断ログの不足: 詳細なログ出力で問題の特定を容易化
技術的詳細:
- Base64エンコードでの署名比較
- タイミング攻撃対策(定数時間比較)
- デバッグモードでの診断ログ出力
2. Result型パターン - 型安全なエラーハンドリング
JavaScriptのtry-catchに代わる、型安全なエラーハンドリングパターンを導入しました。
実装例:
// lib/result.ts
export type Result<T, E> =
| { ok: true; value: T }
| { ok: false; error: E };
// 使用例
async function processWebhook(
event: LineEvent
): Promise<Result<string, string>> {
// 署名検証
const signatureResult = await verifySignature(body, signature, secret);
if (!signatureResult.ok) {
return { ok: false, error: 'Invalid signature' };
}
// メッセージ処理
const response = await handleMessage(event);
if (!response.ok) {
return { ok: false, error: response.error };
}
return { ok: true, value: response.value };
}
利点:
- コンパイル時の型チェック(エラーハンドリング漏れを防止)
- 明示的なエラー型定義
- 関数型プログラミングパターンの適用
3. 構造化ログ - 可観測性の確保
JSON形式の構造化ログで、運用性と診断性を大幅に向上させました。
実装内容:
// lib/logger.ts
interface LogEntry {
timestamp: string;
level: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
event_type: string;
request_id?: string;
user_id?: string;
group_id?: string;
[key: string]: any;
}
export function logInfo(entry: Omit<LogEntry, 'timestamp' | 'level'>) {
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level: 'INFO',
...entry,
}));
}
活用例:
{
"timestamp": "2025-10-15T12:34:56.789Z",
"level": "INFO",
"event_type": "webhook.received",
"request_id": "abc123",
"group_id": "G1234567890",
"message_type": "text"
}
利点:
- Supabase Logsでの検索・フィルタリングが容易
- トラブルシューティングの高速化
- パフォーマンス分析の基盤
4. CI/CDパイプライン - GitHub Actions
自動デプロイとテストを実現するCI/CDパイプラインを構築しました。
ワークフロー定義 (.github/workflows/deploy.yml):
name: Deploy to Supabase
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: Run tests
run: deno test --allow-all
- name: Deploy to Supabase
run: |
npx supabase functions deploy savvybot \
--project-ref ${{ secrets.SUPABASE_PROJECT_REF }}
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
デプロイフロー:
mainブランチへのプッシュ- Denoのセットアップ
- テスト実行(型チェック含む)
- Supabase Edge Functionsへのデプロイ
- 自動ヘルスチェック
利点:
- コードの品質保証(自動テスト)
- デプロイの高速化(手動作業ゼロ)
- リリースの安全性向上
アーキテクチャ
Supabase Edge Functions構成:
supabase/functions/
├── savvybot/
│ ├── index.ts # Webhookエントリーポイント
│ ├── lib/
│ │ ├── security.ts # 署名検証
│ │ ├── line.ts # LINE API連携
│ │ ├── openai.ts # OpenAI API連携
│ │ ├── db.ts # Supabase DB操作
│ │ ├── logger.ts # 構造化ログ
│ │ └── result.ts # Result型定義
│ └── types/
│ └── line.ts # LINE型定義
データフロー:
LINE App
↓ (Webhook POST)
Supabase Edge Function
↓ (署名検証)
セキュリティチェック ✓
↓ (イベント処理)
OpenAI API呼び出し
↓ (応答生成)
LINE Messaging API返信
実機テスト結果
テストシナリオ:
- ✅ 署名検証の成功(正しい署名)
- ✅ 署名検証の失敗(不正な署名 → 403 Forbidden)
- ✅ メッセージ送受信(1対1チャット)
- ✅ レスポンスタイム測定(< 3秒)
パフォーマンス:
- コールドスタート: ~1.5秒
- ウォームスタート: ~500ms
- OpenAI API呼び出し: ~2秒
技術スタック(Phase 2)
ランタイム:
- Deno 1.x
- TypeScript 5.x
インフラ:
- Supabase Edge Functions(Deno Deploy基盤)
- Supabase PostgreSQL(将来のデータ永続化用)
外部API:
- LINE Messaging API(Webhook、Reply API)
- OpenAI API(gpt-3.5-turbo)
DevOps:
- GitHub Actions(CI/CD)
- Supabase CLI
学んだこと
- セキュリティの重要性: 署名検証は必須、タイミング攻撃対策も考慮
- 型安全性の価値: Result型パターンでエラーハンドリング漏れを防止
- 可観測性の基盤: 構造化ログが運用とデバッグを大幅に効率化
- CI/CDの効果: 自動化によりデプロイの安全性と速度が向上
次のステップ
Phase 2でインフラ基盤を確立したことで、次のフェーズではプロダクト機能の拡充に集中できるようになりました。
Phase 2完了日: 2025年10月15日 主な技術的成果: HMAC-SHA256署名検証、Result型エラーハンドリング、構造化ログ、CI/CDパイプライン