Files
opengroupware/docs/architecture.md
Ken Yasue 80e195b3dc chore: initialize repository with project docs and tooling
- Add persistent docs: PRD, functional design, architecture, repository structure, development guidelines, milestones

- Add brainstorming notes (docs/ideas/)

- Configure tooling: package.json, tsconfig, eslint, prettier, vitest

- Add opencode configuration (commands, skills, agents)

- Add .gitignore for node_modules, .env, data/, backups/, build outputs
2026-06-24 23:31:06 +02:00

272 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# アーキテクチャ設計書 (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ルールと連携 |
| TypeScripttsc | 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ファイル・バックアップへのアクセス
- **禁止操作**: 業務ロジックの実装
```typescript
// 許容: 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で再現性を担保
## チェックリスト
- [x] 全技術選定に理由が記載されている
- [x] レイヤードアーキテクチャが明確に定義されている(依存規則含む)
- [x] パフォーマンス要件が測定可能である
- [x] セキュリティ考慮事項が文書化されている
- [x] スケーラビリティが考慮されている
- [x] バックアップ戦略が定義されている
- [x] 依存管理方針が明確である
- [x] テスト戦略が定義されている