# CertRemind 開発計画 ## 目的 CertRemind は、ユーザーが登録した Web サイトの TLS/SSL 証明書の有効期限を監視し、期限切れ前に Web アプリ内アラート、Webhook、プッシュ通知で知らせるサービスである。 この計画では、初期実装から運用可能な MVP までを段階的に進める。 ## 前提 - Node.js v22 を使用する。 - パッケージ管理は pnpm を使用する。 - バックエンドは Hono.js を使用する。 - フロントエンドは React.js と Radix UI を使用する。 - データベースは PostgreSQL を使用する。 - 証明書情報の取得には OpenSSL を使用する。 - セキュリティ上、クライアントから送信された値は信頼しない。 - CSRF 対策、セッション管理、パスワードハッシュ、入力検証を初期段階から組み込む。 ## 全体方針 1. まず認証、DB、基本画面、API の土台を作る。 2. 次にサイト登録、通知条件、アラート履歴までの主要業務フローを作る。 3. その後、バックグラウンド監視、Webhook、プッシュ通知を追加する。 4. 最後に 2 段階認証、アカウント削除、監視停止保証、テスト、運用設定を固める。 ## 推奨ディレクトリ構成 ```text . ├── AGENTS.md ├── development_plan.md ├── package.json ├── pnpm-lock.yaml ├── docker-compose.yml ├── .env.example ├── db │ ├── migrations │ └── schema.sql ├── src │ ├── server │ │ ├── app.js │ │ ├── index.js │ │ ├── config │ │ ├── db │ │ ├── middleware │ │ ├── modules │ │ │ ├── auth │ │ │ ├── users │ │ │ ├── sites │ │ │ ├── alerts │ │ │ ├── notificationMethods │ │ │ └── monitoring │ │ └── jobs │ └── client │ ├── main.jsx │ ├── App.jsx │ ├── routes │ ├── components │ ├── api │ └── styles └── tests ``` ## データベース設計方針 AGENTS.md の論理定義を基準に、実装時には次の補足を加える。 - 全テーブルに `created_at` と `updated_at` を持たせる。 - 主キーは UUID を基本とする。 - ユーザー ID に紐づくデータは外部キーで整合性を保つ。 - アカウント削除時にユーザー関連データを確実に削除できるよう、外部キーの削除動作を設計する。 - サイトにはエイリアス名が必要なため `alias` を追加する。 - 通知方法は複数 Webhook に対応するため、主キーは `notification_method_id` とし、`user_id` は外部キーにする。 - プッシュ通知はブラウザ購読情報を保持するため、endpoint と key 情報を保存できるテーブルを用意する。 - アラート履歴には既読状態、対象サイト、発生日時、通知種別、送信結果を保存する。 - 同じ条件でアラートを連続送信しすぎないよう、通知済み状態または抑制用の履歴を持つ。 ## 実装フェーズ ### フェーズ 0: プロジェクト基盤 目的: 開発を進められる最小構成を整える。 作業: - pnpm ベースの依存関係を追加する。 - Hono サーバーを起動できるようにする。 - React/Vite のフロントエンドを構成する。 - PostgreSQL 用の `docker-compose.yml` を作成する。 - `.env.example` を作成する。 - DB 接続モジュールを作る。 - マイグレーション管理方法を決める。 - ESLint、Formatter、テストランナーを導入する。 成果物: - 開発サーバーが起動できる。 - PostgreSQL が Docker で起動できる。 - ヘルスチェック API が動く。 ### フェーズ 1: 認証とセッション 目的: ユーザー登録、ログイン、ログアウト、セッション管理を実装する。 作業: - ユーザーテーブルの DDL を作成する。 - パスワードを Argon2id などの強力な方式でハッシュ化する。 - 登録 API を作る。 - ログイン API を作る。 - ログアウト API を作る。 - 現在のユーザー取得 API を作る。 - CSRF トークンを導入する。 - 認証必須ミドルウェアを作る。 - 登録画面、ログイン画面を作る。 注意: - ユーザー名はユニーク制約を必須にする。 - 認証エラーでは、ユーザー名の存在有無が推測されにくいレスポンスにする。 - セッション Cookie は `HttpOnly`、`SameSite`、本番では `Secure` を有効にする。 ### フェーズ 2: サイト管理 目的: 監視対象サイトを登録、表示、編集、削除できるようにする。 作業: - サイトテーブルの DDL を作成する。 - サイト登録 API を作る。 - サイト一覧 API を作る。 - サイトエイリアス更新 API を作る。 - サイト削除 API を作る。 - URL の正規化と検証を実装する。 - サイト一覧画面を作る。 注意: - リクエスト上の `user_id` は信用せず、必ずセッションから取得する。 - URL は `https://` を基本とし、ホスト名を検証する。 - 削除時は関連する通知条件と監視状態も削除する。 ### フェーズ 3: サイト設定と通知条件 目的: サイトごとに通知タイミングと通知方法を設定できるようにする。 作業: - サイトアラート条件テーブルの DDL を作成する。 - 通知条件の取得、作成、更新、削除 API を作る。 - 通知タイミングを内部的には時間単位で保存する。 - UI では時間、日、週間で指定できる入力を作る。 - Web アプリ内アラートは必須通知先として扱う。 - サイト設定画面を作る。 注意: - 0 以下の通知時間、過大な値、不正な単位を拒否する。 - 同じサイトに同一条件が重複しないように制約またはアプリ側検証を入れる。 ### フェーズ 4: アラート履歴 目的: システムが送信したアラートを Web アプリ内で確認できるようにする。 作業: - アラート履歴テーブルの DDL を作成する。 - アラート一覧 API を作る。 - 既読更新 API を作る。 - サイト、日時、アラート種類で絞り込める API を作る。 - アラート一覧画面を作る。 注意: - 履歴はユーザー単位で必ず分離する。 - 絞り込み条件は SQL インジェクションを避けるため、プレースホルダを使用する。 ### フェーズ 5: 通知方法管理 目的: Webhook とプッシュ通知の設定を管理できるようにする。 作業: - 通知方法テーブルの DDL を作成する。 - Webhook 登録、一覧、更新、削除 API を作る。 - Webhook URL とエイリアス名の検証を実装する。 - プッシュ通知の購読情報登録 API を作る。 - VAPID key を設定ファイルから読み込む。 - 通知方法管理画面を作る。 注意: - Webhook URL は HTTPS を推奨し、ローカルアドレスやメタデータ IP への SSRF を防ぐ。 - Slack 互換 Webhook の送信形式を固定する。 - プッシュ通知はブラウザ許可状態を UI に反映する。 ### フェーズ 6: 証明書監視ジョブ 目的: 登録サイトの証明書期限を取得し、条件に合う場合にアラートを送信する。 作業: - OpenSSL を呼び出して証明書の期限を取得する処理を作る。 - 監視対象サイトをユーザー単位で取得する。 - サイトごとの通知条件を評価する。 - 条件に一致したらアラート履歴を作成する。 - Webhook 通知を送信する。 - プッシュ通知を送信する。 - 二重送信を防ぐ仕組みを作る。 - ジョブ実行ログを残す。 注意: - OpenSSL 呼び出しはタイムアウトを設定する。 - 1 件の監視失敗が全体を止めないようにする。 - 外部通信と証明書取得は並列数を制限する。 - 証明書取得失敗もアラート種類として扱う。 ### フェーズ 7: アカウント設定と 2 段階認証 目的: ユーザー情報、パスワード、2 段階認証、アカウント削除を実装する。 作業: - 表示名更新 API を作る。 - パスワード更新 API を作る。 - パスワード更新時に全セッションを無効化する。 - OTP シークレット登録、検証、解除 API を作る。 - ログインフローに 2 段階認証を組み込む。 - アカウント削除 API を作る。 - アカウント設定画面を作る。 注意: - 2 段階認証解除には再認証を求める。 - アカウント削除時は監視対象、通知先、アラート履歴、セッションをすべて削除する。 - 削除後に監視ジョブが対象ユーザーを処理しないことを確認する。 ### フェーズ 8: 品質向上と運用準備 目的: セキュリティ、安定性、テスト、運用手順を整える。 作業: - API の単体テストを追加する。 - 認証、サイト管理、通知条件、アラート履歴の統合テストを追加する。 - 証明書監視処理のテストを追加する。 - CSRF、認可漏れ、SSRF、入力検証の観点でレビューする。 - エラーハンドリングとログ出力を整理する。 - README に開発環境起動手順を追加する。 - 本番向け環境変数の一覧を整理する。 ## API 設計メモ 初期案として、以下のようにリソース単位で分ける。 ```text POST /api/auth/register POST /api/auth/login POST /api/auth/logout GET /api/auth/me GET /api/auth/csrf GET /api/sites POST /api/sites GET /api/sites/:siteId PATCH /api/sites/:siteId DELETE /api/sites/:siteId GET /api/sites/:siteId/settings PUT /api/sites/:siteId/settings DELETE /api/sites/:siteId/settings GET /api/alerts PATCH /api/alerts/:alertId/read GET /api/notification-methods POST /api/notification-methods/webhooks PATCH /api/notification-methods/webhooks/:methodId DELETE /api/notification-methods/webhooks/:methodId POST /api/notification-methods/push-subscriptions GET /api/account PATCH /api/account/profile PATCH /api/account/password POST /api/account/totp/setup POST /api/account/totp/verify DELETE /api/account/totp DELETE /api/account ``` ## 画面実装順 1. 登録画面 2. ログイン画面 3. サイト一覧 4. サイト設定 5. アラート一覧 6. 通知方法の管理 7. アカウント設定 ## セキュリティチェックリスト - パスワードを平文保存しない。 - 認証が必要な API ではセッションからユーザーを特定する。 - 他ユーザーのサイト、通知先、アラート履歴にアクセスできないことをテストする。 - CSRF トークンを状態変更 API に必須化する。 - Cookie に `HttpOnly`、`SameSite`、本番 `Secure` を設定する。 - Webhook 送信先の SSRF 対策を行う。 - OpenSSL 呼び出しにタイムアウトを設定する。 - 外部入力はスキーマ検証する。 - SQL はプレースホルダを使う。 - アカウント削除で関連データが残らないことを確認する。 ## MVP の完了条件 - ユーザーが登録、ログイン、ログアウトできる。 - ユーザーが監視対象サイトを登録、一覧、編集、削除できる。 - サイトごとに通知タイミングを設定できる。 - 証明書期限を監視してアラート履歴に記録できる。 - Webhook に通知できる。 - アラート一覧で履歴を確認し、既読にできる。 - 基本的な認可テストと入力検証テストが通る。 ## MVP 後に追加する機能 - プッシュ通知 - 2 段階認証 - パスワード更新時の全セッション無効化 - アカウント削除時の完全削除と監視停止保証 - 監視ジョブの詳細ログと管理用メトリクス - 通知失敗時のリトライ制御 ## 初回実装の推奨タスク 1. Hono と React/Vite の最小構成を作成する。 2. Docker Compose で PostgreSQL を起動できるようにする。 3. DB マイグレーションまたは `db/schema.sql` を作成する。 4. 認証 API とセッション管理を実装する。 5. 登録画面とログイン画面を実装する。 6. サイト管理 API とサイト一覧画面を実装する。