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
This commit is contained in:
2026-06-24 23:31:06 +02:00
commit 80e195b3dc
51 changed files with 12716 additions and 0 deletions

271
docs/architecture.md Normal file
View File

@ -0,0 +1,271 @@
# アーキテクチャ設計書 (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] テスト戦略が定義されている