アーキテクチャ設計書 (Architecture Design Document)
本書は docs/product-requirements.md と docs/functional-design.md を技術的に実現するためのシステム構造・技術選定・インフラ要件を定義する。
技術スタック
言語・ランタイム
| 技術 |
バージョン |
選定理由 |
| Node.js |
v24.11.0 |
開発環境(devcontainer)と同一。better-sqlite3の同期APIを直接扱える。LTS保証下で本番運用が安定 |
| TypeScript |
5.x |
静的型付けによりコンパイル時バグ検出。Repository/Service/Entity間の型共有で保守性向上。IDE補完により開発効率向上 |
| npm |
11.x |
Node.js v24.11.0にバンドル。package-lock.jsonによる厳密な依存管理。workspaces対応 |
フレームワーク・ライブラリ
| 技術 |
バージョン |
目的 |
選定理由 |
| Next.js |
15 |
Webフレームワーク |
App Router・Server Components・Route Handlers・Server Actionsを統合利用。Node.js Runtime選択可能でSQLite直接操作に適合 |
| better-sqlite3 |
最新安定 |
SQLiteドライバ |
同期APIで扱いやすく高速。トランザクション・プリペアドステートメント・pragma制御が直接可能 |
| react-markdown |
最新安定 |
Markdownレンダリング |
GFM拡張と連携可能。プラグインでサニタイズパイプラインを構築できる |
| remark-gfm |
最新安定 |
GFM対応 |
テーブル・チェックリスト・取り消し線等のGFM記法を有効化 |
| rehype-sanitize |
最新安定 |
HTMLサニタイズ |
Markdown表示時のXSS対策。危険なHTML・URLスキームを除去 |
| Tailwind CSS |
最新安定 |
スタイリング |
ユーティリティファーストでUI構築が高速。カスタムCSS削減 |
| bcrypt |
最新安定 |
パスワードハッシュ |
ソルト付きハッシュで平文保存を回避。適切なコスト係数でブルートフォース耐性 |
| FullCalendar系 または独自実装 |
- |
カレンダーUI |
月/週/日/リスト表示・ドラッグ操作・イベントフィルタ要件を満たす |
開発ツール
| 技術 |
バージョン |
目的 |
選定理由 |
| Vitest |
最新安定 |
Unit Test |
Viteベースで高速。TypeScriptネイティブ対応。better-sqlite3等のネイティブモジュールも扱える |
| Playwright |
最新安定 |
E2E Test |
実ブラウザ(Chromium/Firefox/WebKit)操作で主要ユーザーフローを検証。SSEのリアルタイム挙動も検証可能 |
| ESLint |
最新安定 |
リンタ |
コード品質・一貫性維持。TypeScriptルールと連携 |
| TypeScript(tsc) |
5.x |
型チェック |
型エラーをCIで検出 |
アーキテクチャパターン
レイヤードアーキテクチャ
┌─────────────────────────────────────────────┐
│ UI層 (Next.js) │ ← Server Components / Client Components
│ Route Handler / Server Action / SSE │ 入力受付・表示・認証・認可
├─────────────────────────────────────────────┤
│ Service層 │ ← 業務ロジック・権限チェック・トランザクション
│ AuthService / ProjectService / ... │ 通知生成・アクティビティログ・SSE配信
├─────────────────────────────────────────────┤
│ Repository層 │ ← SQL保持・データアクセス・論理削除フィルタ
│ UserRepository / ProjectRepository / ... │
├─────────────────────────────────────────────┤
│ Data層 │ ← SQLite接続・SQL実行・Migration
│ lib/db/sqlite.ts / migrator.ts / SQLite │
└─────────────────────────────────────────────┘
レイヤ責務と依存規則
依存は一方向(UI → Service → Repository → Data)のみ許可する。逆方向依存・層飛ばしを禁止する。
UI層(Route Handler / Server Action / Server Components / SSEエンドポイント)
- 責務: 入力受付・バリデーション・認証・認可・結果表示
- 許可操作: Service層の呼び出し
- 禁止操作: Repository層・Data層への直接アクセス、SQLの直接記述
Service層
- 責務: 業務ロジック・権限チェック(
isMember/ロール)・トランザクション境界・副作用(通知生成・アクティビティログ記録・SSE配信)
- 許可操作: Repository層の呼び出し・FileStorageServiceによるファイル操作・SseHubへの配信依頼
- 禁止操作: UI層への依存、SQLの直接記述、SQLiteライブラリの直接操作
Repository層
- 責務: SQLの保持・パラメータバインド実行・論理削除(
deleted_at IS NULL)の確実な付与・プロジェクト分離の担保
- 許可操作: SQLラッパー(
lib/db/sqlite.ts)経由のDBアクセス
- 禁止操作: 業務ロジックの実装、SQLiteライブラリの直接操作、UI層への依存
Data層
- 責務: SQLite接続の共通管理・SQL実行・トランザクション・Migration
- 許可操作: better-sqlite3へのアクセス・ファイルシステム(Migrationファイル・バックアップ)へのアクセス
- 禁止操作: 業務ロジックの実装
// 許容: UI → Service → Repository → Data
routeHandler → projectService.createProject(...) → projectRepository.create(...) → db.execute(sql, params)
// 禁止: UI → Data (層飛ばし)
routeHandler → db.execute("INSERT INTO projects ...") // ❌
// 禁止: Repository → SQLite直接 (ラッパー未使用)
projectRepository → new Database(dbPath) // ❌
ランタイム方針
SQLiteを直接扱うため、Next.jsのEdge Runtimeは使用しない。API Route・Server Actions・DBアクセス処理・SSEエンドポイントはすべてNode.js Runtimeで実行する。各Route Handlerの先頭で export const runtime = 'nodejs' を明示する。
Prisma不使用の方針
DBアクセスは独自SQLラッパー(lib/db/sqlite.ts)とRepositoryクラスで実装する。Prismaは導入しない。
- 理由1: SQLを直接制御することでクエリ最適化・インデックス設計を明示できる
- 理由2: better-sqlite3の同期APIと相性が良く、コード生成のオーバーヘッドがない
- 理由3: MigrationもSQLファイルベースの独自実装でバージョン管理する
データ永続化戦略
保存方式
| データ種別 |
保存先 |
形式 |
理由 |
| アプリケーションデータ |
SQLite(./data/app.db) |
リレーショナル |
トランザクション・外部キー・インデックス・論理削除を一貫管理 |
| アップロードファイル |
ローカルFS(./data/uploads/<projectId>/) |
バイナリ |
外部ストレージ不要・自己完結。DBにメタデータ(file_assets)を保存 |
| Migration履歴 |
SQLite(schema_migrations) |
行レコード |
適用済みファイルを一意管理・再実行回避 |
| バックアップ |
ローカルFS(./backups/) |
ZIP |
DBファイル+uploadsディレクトリをZIP化 |
SQLite接続設定
journal_mode = WAL: 読み書きの並行性向上
foreign_keys = ON: 外部キー制約・カスケード削除を有効化
- 接続はシングルトン(
getDb())で共有。dbPathは process.env.SQLITE_PATH ?? "./data/app.db"
バックアップ戦略
- 作成タイミング: 管理者がバックアップ画面から手動実行
- 作成内容: SQLite DBファイル + uploadsディレクトリをZIP化
- 保存先:
./backups/backup-<timestamp>.zip
- 世代管理: 一覧表示・ダウンロード可能(世代数は運用で定義)
- リストア手順: サーバ停止 → ZIP展開 →
./data/app.db と ./data/uploads/ を差替 → サーバ再起動
パフォーマンス要件
応答時間
| 操作 |
目標時間 |
測定環境 |
| チャットSSE配信遅延 |
送信から全クライアント受信まで3秒以内(95パーセンタイル) |
小規模同時接続(数十) |
| 一覧画面表示 |
1000件データ時1秒以内(掲示板・チャット履歴・ファイル一覧・Markdownメモ) |
ページネーション20件/頁 |
| バックアップ作成 |
DB+uploads合計100MB相当で30秒以内 |
ローカルFS |
| Migration実行 |
1ファイル1トランザクション・失敗時即座ロールバック |
初回スキーマ適用 |
リソース使用量
| リソース |
上限 |
理由 |
| メモリ |
Next.jsサーバプロセス1GB程度 |
1プロジェクト数十人規模・小規模同時接続前提 |
| CPU |
単一サーバで十分 |
SQLite同期処理・SSE数十接続を想定 |
| ディスク |
DB+uploads合計数百MB〜数GBを想定 |
バックアップは別途容量確保 |
パフォーマンス最適化施策
- ページネーション: 全一覧APIで
?page=&pageSize= を必須化し必要件数のみ取得
- インデックス:
project_notes(project_id), project_notes(updated_at) 等の高頻度検索カラムにインデックス付与
- Server Components: 可能な限りServer Componentsでデータ取得しクライアント送信量を削減
- WALモード: 読み書き並行性向上
- SSE配信のスコープ限定: プロジェクト単位でクライアント集合を管理し、無関係プロジェクトへの配信コストを排除
セキュリティアーキテクチャ
データ保護
- パスワード保護: bcryptでハッシュ化保存。平文保存禁止。ソルト付き・適切なコスト係数
- 暗号化: 通信はHTTPS前提。保存時のDBファイル暗号化は本スコープ外(ローカルFSのアクセス権限で保護)
- アクセス制御: サーバプロセスのファイル権限により
./data/, ./backups/ を保護
- 機密情報管理: 設定は
.env で管理(SQLITE_PATH 等)。コード内にハードコード禁止。.env はリポジトリにコミットしない
認証・認可
- 認証: 独自ログイン方式・セッションベース。未認証リクエストは保護画面/APIにアクセス不可(401/リダイレクト)
- 認可(プロジェクト): Service層で
ProjectMemberRepository.isMember(projectId, userId) を必ず実施。非参加者は403
- 認可(管理者機能): バックアップ・Migration状態確認は
role='system_admin' のみ許可
- ファイルアクセス: ダウンロードAPIでもプロジェクト参加権限をチェック
入力バリデーション
- バリデーション: 全入力で必須チェック・長さ制限(タイトル1-200文字等)・形式チェックをService層で実施
- SQL対策: 全SQLをパラメータバインドで実行。文字列結合によるSQL構築は禁止
- Markdownサニタイズ: HTML直接入力無効化 + rehype-sanitize でサニタイズ + 危険URLスキーム(
javascript:等)除外
- ファイルアップロード: MIMEタイプチェック・ファイル名サニタイズ・保存名の一意化(
<uuid>.<ext>)
- エラー表示: スタックトレース・内部情報を本番では非表示。ユーザーには抽象メッセージのみ表示
監査
- 管理者操作・主要な変更操作をアクティビティログに記録(
activity_logs テーブル)
スケーラビリティ設計
データ増大への対応
- 想定データ量: 1プロジェクトあたり数十人・数千〜数万レコード(チャット・掲示板・アクティビティログが主要)
- 性能劣化対策:
- ページネーションによる取得件数制限
- インデックス最適化(検索頻度高いカラム)
- 論理削除データの取得除外(
deleted_at IS NULL を全取得クエリに付与)
- アーカイブ戦略: 完了/アーカイブ済みプロジェクトは
status='archived' で残置。大量データの物理削除は本スコープ外(運用で判断)
拡張性
- プラグインシステム: なし(本スコープ外)
- 設定カスタマイズ:
.env による設定管理(SQLITE_PATH・ uploadsパス等)
- API拡張性: Route Handlerベースでリソースごとにエンドポイントを分割。将来の公開REST API化はPost-MVP
- SSEイベント拡張:
SseEvent 型に新種別を追加するだけで新イベント配信が可能
テスト戦略
Unit Test
- フレームワーク: Vitest
- 対象: SQLラッパー・Migration・全Repository・全Service・権限チェック・バリデーション・スケジュール重複判定・通知作成ロジック・アクティビティログ作成ロジック・マイルストーン進捗計算
- カバレッジ目標: Repository/Service層 80%以上
- 実行コマンド:
npm test
統合テスト
- 方法: Vitestで実際のSQLite(一時ファイル)を使用
- 対象: 認証フロー・プロジェクト作成→メンバー追加→権限分離・チャット送信→SSE配信
E2E Test
- ツール: Playwright
- シナリオ: 認証・プロジェクト管理・掲示板・チャット(SSEリアルタイム)・ToDo(ドラッグ&ドロップ)・ファイル共有(Lightbox)・Markdownメモ・カレンダー・ミーティング(予定重複警告)・通知・アクティビティログ・バックアップ
- 実行コマンド:
npm run test:e2e
技術的制約
環境要件
- OS: devcontainer(開発)/ Linux想定(本番)。Windows・macOSでもNode.js Runtime動作可能
- 最小メモリ: 1GB
- 必要ディスク: DB+uploads+backups(数百MB〜数GB)
- 必須外部依存: なし(外部DB・外部ストレージ・外部IdPに非依存・自己完結)
パフォーマンス制約
- 1プロジェクトあたり数十人規模を想定(数百人規模はスコープ外)
- チャットSSEは小規模同時接続(数十接続)を前提
- 一覧取得は必ずページネーション(全件取得禁止)
セキュリティ制約
- 認証必須(
/api/auth/*除く)
- 全SQLパラメータバインド(文字列結合禁止)
- Markdown表示時のHTML無効化・サニタイズ必須
- パスワード平文保存禁止
ランタイム制約
- Edge Runtime使用禁止(SQLite直接操作のため全てNode.js Runtime)
- Prisma使用禁止
依存管理
| ライブラリ |
目的 |
バージョン管理方針 |
| next |
フレームワーク |
固定(破壊的変更リスク大) |
| react / react-dom |
UI |
^(マイナーアップ許容) |
| better-sqlite3 |
SQLiteドライバ |
^(ネイティブビルド要注意) |
| react-markdown / remark-gfm / rehype-sanitize |
Markdown |
^(マイナーアップ許容) |
| bcrypt |
パスワードハッシュ |
^ |
| tailwindcss |
スタイリング |
^ |
| typescript |
型チェック |
~(パッチのみ自動・devDependencies) |
| vitest |
Unit Test |
^(devDependencies) |
| @playwright/test |
E2E Test |
^(devDependencies) |
| eslint |
リンタ |
^(devDependencies) |
方針:
- 安定版は
^ でマイナーアップを許容
- 破壊的変更リスクのあるもの(next等)は固定
- devDependenciesは
~ でパッチのみ自動アップ許容
- package-lock.jsonで厳密にロックしCIで再現性を担保
チェックリスト