logo

SavvyBot Phase 1-2
基盤構築とセキュリティ強化

AI / チャットボット開発バックエンド開発 / DevOps2023年3月〜2025年10月2025-11-07

GAS MVPからSupabase Edge Functionsへの移行完了。HMAC-SHA256署名検証の実装、Result型によるエラーハンドリング、CI/CDパイプライン構築を完了し、堅牢なインフラ基盤を確立。

Technologies Used

Supabase Edge FunctionsLINE Messaging APIOpenAI APIDenoTypeScriptGitHub ActionsWeb Crypto API

SavvyBot Phase 1-2 ― 基盤構築とセキュリティ強化

← プロジェクト概要に戻る | Phase 3-4へ →

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)
  );
}

解決したバグ:

  1. 非同期Web Crypto APIの誤使用: Node.js の crypto モジュールを使用することで解決
  2. 定数時間比較の欠如: タイミング攻撃を防ぐため timingSafeEqual() を実装
  3. 診断ログの不足: 詳細なログ出力で問題の特定を容易化

技術的詳細:

  • 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 }}

デプロイフロー:

  1. main ブランチへのプッシュ
  2. Denoのセットアップ
  3. テスト実行(型チェック含む)
  4. Supabase Edge Functionsへのデプロイ
  5. 自動ヘルスチェック

利点:

  • コードの品質保証(自動テスト)
  • デプロイの高速化(手動作業ゼロ)
  • リリースの安全性向上

アーキテクチャ

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返信

実機テスト結果

テストシナリオ:

  1. ✅ 署名検証の成功(正しい署名)
  2. ✅ 署名検証の失敗(不正な署名 → 403 Forbidden)
  3. ✅ メッセージ送受信(1対1チャット)
  4. ✅ レスポンスタイム測定(< 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

学んだこと

  1. セキュリティの重要性: 署名検証は必須、タイミング攻撃対策も考慮
  2. 型安全性の価値: Result型パターンでエラーハンドリング漏れを防止
  3. 可観測性の基盤: 構造化ログが運用とデバッグを大幅に効率化
  4. CI/CDの効果: 自動化によりデプロイの安全性と速度が向上

次のステップ

Phase 2でインフラ基盤を確立したことで、次のフェーズではプロダクト機能の拡充に集中できるようになりました。

→ Phase 3-4: グループチャット特化へ


Phase 2完了日: 2025年10月15日 主な技術的成果: HMAC-SHA256署名検証、Result型エラーハンドリング、構造化ログ、CI/CDパイプライン

#Supabase Edge Functions#HMAC-SHA256#署名検証#Deno#TypeScript#GitHub Actions#CI/CD

©2025 Natsuki Hayashida. All Rights Reserved.