# セキュリティ設計書

## 概要

本ドキュメントは、Fizzy（タスク/カード管理システム）のセキュリティ設計について記述する。Ruby on Rails 8.xをベースとしたWebアプリケーションにおける認証・認可・データ保護・入出力対策・監査ログ等のセキュリティ機構の設計方針と実装詳細を定義する。

## 認証設計

### 認証方式

本システムはパスワードレス認証（Magic Link方式）を採用している。

| 項目 | 内容 |
| --- | --- |
| 認証方式 | Magic Link（メールベースのワンタイムコード） |
| コード生成 | SecureRandom.base32による6桁のランダムコード |
| コード有効期限 | 15分間（EXPIRATION_TIME = 15.minutes） |
| コード検証 | タイミング攻撃対策としてActiveSupport::SecurityUtils.secure_compareを使用 |
| レート制限 | ログイン試行: 3分間に10回まで / コード検証: 15分間に10回まで |

### 認証フロー

1. ユーザーがメールアドレスを入力
2. システムがMagicLinkを生成し、メールでコードを送信
3. ユーザーが受信したコードを入力
4. コード検証成功時、新規セッションを作成
5. 署名付きセッショントークンをCookieに設定

### APIトークン認証

Bearer Token方式によるAPI認証も提供している。

| 項目 | 内容 |
| --- | --- |
| トークン種別 | Identity::AccessToken |
| トークン生成 | has_secure_tokenによる自動生成 |
| 権限レベル | read（GET/HEADのみ）/ write（全メソッド） |
| 認証ヘッダー | Authorization: Bearer {token} |

### セッション管理

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| セッション有効期限 | 永続（permanent） | 署名付きCookie使用 |
| セッション固定化対策 | 認証成功時に新規セッション作成 | start_new_session_forメソッド |
| セッションCookie属性 | httponly: true, same_site: :lax | XSS/CSRF対策 |
| セッション識別子 | Session.signed_id | Rails署名付きID使用 |
| セッション情報 | IP Address, User Agent記録 | 監査用 |

## 認可設計

### 権限体系

| ロール | 権限 | 説明 |
| --- | --- | --- |
| owner | 全権限 | アカウントオーナー。admin権限を包含 |
| admin | 管理権限 | ユーザー管理、ボード管理等の管理機能 |
| member | 一般権限 | カード作成・編集、コメント等の基本機能 |
| system | システム用 | 自動化処理用の内部ユーザー |

### アクセス制御

本システムは複数層のアクセス制御を実装している。

#### アカウントレベル

- マルチテナント方式でアカウント（テナント）間のデータ分離を実現
- Current.accountによるリクエストスコープでのテナント特定
- 全テーブルにaccount_idカラムを保持し、クエリ時にスコープ適用

#### ボードレベル

- Access モデルによるボード単位のアクセス制御
- all_access フラグによる全ユーザーアクセス許可機能
- ボード作成者は自動的にアクセス権付与（watching状態）

#### カードレベル

- ボードのアクセス権限を継承
- 公開設定（published）と非公開設定のサポート
- Board::Publicationによる外部公開機能（secure token使用）

#### 操作レベル

- can_change?, can_administer?, can_administer_board?, can_administer_card? メソッドによる細粒度の権限チェック
- オーナーは他のオーナー以外の全ユーザーを管理可能
- 管理者は一般メンバーのみ管理可能

### 認可フィルター

| フィルター | 適用 | 説明 |
| --- | --- | --- |
| require_authentication | before_action | 認証必須（デフォルト） |
| ensure_can_access_account | before_action | アカウントへのアクセス権確認 |
| ensure_admin | 手動呼出 | 管理者権限必須 |
| ensure_staff | 手動呼出 | スタッフ権限必須 |

## 通信セキュリティ

| 項目 | 対策 |
| --- | --- |
| HTTPS | 本番環境でforce_ssl = true（環境変数で制御可能） |
| HSTS | assume_ssl = trueによるStrict-Transport-Security有効化 |
| SSL終端 | リバースプロキシでのSSL終端を想定（ASSUME_SSL設定） |

## データセキュリティ

### 暗号化

| 対象 | 暗号化方式 |
| --- | --- |
| 通信 | TLS（HTTPS必須） |
| セッショントークン | Rails署名付きID（signed_id） |
| APIトークン | SecureRandomによる暗号学的に安全なトークン生成 |
| Webhook署名シークレット | has_secure_tokenによる自動生成 |
| 公開ボードキー | has_secure_tokenによる自動生成 |
| 転送用ID | 署名付きID（目的限定、4時間有効期限） |

### 機密情報管理

| 対象 | 管理方式 |
| --- | --- |
| パラメータフィルタリング | passw, secret, token, _key, crypt, salt, certificate, otp, ssn |
| 環境変数 | Rails credentials / ENV経由での機密情報管理 |
| 開発環境のMagic Link | 本番環境ではFlashへの露出を防止（例外発生） |

## 入出力対策

| 脅威 | 対策 |
| --- | --- |
| XSS | Content Security Policy (CSP)の実装。script-src, style-src, img-src等の制御。nonce生成によるインラインスクリプト制御。Rails::HTML5::SafeListSanitizerによるHTMLサニタイズ |
| SQLインジェクション | Active Record ORM使用による自動エスケープ。パラメータバインディングの徹底 |
| CSRF | protect_from_forgery using: :header_only, with: :exception。Sec-Fetch-Siteヘッダーによる検証。same_site: :lax Cookie属性 |

### Content Security Policy詳細

| ディレクティブ | 設定値 |
| --- | --- |
| default-src | 'self' |
| script-src | 'self' (nonce利用) |
| style-src | 'self' 'unsafe-inline' |
| img-src | 'self' blob: data: https: |
| connect-src | 'self' |
| frame-src | 'self' |
| object-src | 'none' |
| base-uri | 'none' |
| form-action | 'self' |
| frame-ancestors | 'self' |
| font-src | 'self' data: https: |
| media-src | 'self' blob: data: https: |
| worker-src | 'self' blob: |

CSP設定は環境変数（CSP_*）またはconfig.x.content_security_policy経由でカスタマイズ可能。

### 入力検証

| モデル | バリデーション |
| --- | --- |
| Identity | email_address: URI::MailTo::EMAIL_REGEXP形式検証、正規化（strip.downcase） |
| MagicLink | code: uniqueness, presence |
| Webhook | url: 許可スキーム（http, https）のみ |
| User | name: presence |
| Tag | title: 形式検証 |

## 監査ログ

| ログ種別 | 記録内容 | 保持期間 |
| --- | --- | --- |
| イベントログ（Event） | カード操作、コメント操作、タイトル変更等のアプリケーションイベント | 永続（データベース保存） |
| セッションログ（Session） | ユーザーエージェント、IPアドレス | セッション期間中 |
| Webhookデリバリー（Webhook::Delivery） | リクエスト/レスポンス、状態 | 永続（データベース保存） |
| ストレージエントリ（Storage::Entry） | 操作種別、差分、リクエストID、ユーザーID | 永続（データベース保存） |
| アプリケーションログ | request_idタグ付きログ | ログローテーション設定に依存 |

### イベント追跡

Eventableモジュールにより、以下のアクションが自動的に記録される：

- カード: 作成、公開、クローズ、再オープン、タイトル変更、ボード変更、延期、自動延期、トリアージ等
- コメント: 作成

## 追加セキュリティ機能

### レート制限

| エンドポイント | 制限 |
| --- | --- |
| セッション作成 | 3分間に10回 |
| Magic Link検証 | 15分間に10回 |

### ブラウザ制限

```ruby
allow_browser versions: :modern
```
モダンブラウザのみアクセスを許可。

### 検索エンジンインデックス制御

BlockSearchEngineIndexingモジュールにより、必要に応じて検索エンジンのインデックスをブロック。

### UUID主キー

全テーブルでUUID型の主キーを使用し、連番によるID推測攻撃を防止。

## 備考

### セキュリティ関連Gem

- brakeman: 静的セキュリティ解析ツール
- bundler-audit: 依存関係の脆弱性チェック
- bcrypt: セキュアなハッシュ生成

### 開発時の注意事項

- Magic LinkコードはRails.env.development?時のみFlashで表示可能
- 本番環境ではFlashへのMagic Link露出時に例外発生
- CSPはDISABLE_CSP環境変数で無効化可能（開発・デバッグ用）
