技術アーキテクチャ

GEO Wiki Pro の技術アーキテクチャの詳細、フロントエンド、バックエンド、ストレージ、セキュリティ設計を含む

## アーキテクチャ概要 GEO Wiki Pro は**フロントエンド・バックエンド分離**アーキテクチャを採用。フロントエンドはシングルページアプリケーション(SPA)、バックエンドは RESTful API サービスです。システム全体の設計は**ファイル即データベース**の概念に従い、従来のデータベースは不要です。 ``` ┌─────────────────┐ ┌─────────────────┐ │ │ │ │ │ Vue 3 SPA │────▶│ Express.js API │ │ (Vite 5) │ │ (Node.js 22) │ │ │ │ │ └─────────────────┘ └────────┬────────┘ │ ┌────────────┴────────────┐ │ │ ┌─────┴─────┐ ┌───────┴───────┐ │ Markdown │ │ アップロード │ │ ファイル │ │ されたメディア │ │ ストレージ│ │ ファイルストレージ│ └───────────┘ └───────────────┘ ``` ## フロントエンドアーキテクチャ ### 技術スタック - **フレームワーク**: Vue 3(Composition API) - **ビルドツール**: Vite 5 - **スタイリング**: Tailwind CSS 3.4 - **状態管理**: Pinia - **ルーティング**: Vue Router 4 - **検索**: Fuse.js(クライアント側あいまい検索) ### ディレクトリ構造 ``` src/ pages/ # 20 個のページコンポーネント、ルートマッピング components/ # 24 個の再利用可能コンポーネント stores/ # Pinia ステートストア: docsStore, uiStore, siteConfigStore api/ # API クライアントモジュール client.js # apiClient オブジェクトをエクスポート request.js # request()(認証済み)+ requestPublic()(未認証) docs.js # ドキュメント CRUD + 検索 auth.js # ログイン/ログアウト/登録 llm.js # AI 機能 admin.js # 管理ダッシュボード API utils/ # ユーティリティ関数: i18n.js, markdown.js, icons.js, schema.js i18n/ # 翻訳ファイル: zh.json, en.json, jp.json ``` ### コアモジュール - **docsStore**: ドキュメントリスト、カテゴリ、タグの状態とキャッシュを管理 - **uiStore**: UI 状態(言語、サイドバー、テーマなど)を管理 - **siteConfigStore**: サイト設定(Hero セクション、ロゴ、特集ドキュメントなど)を管理 ## バックエンドアーキテクチャ ### 技術スタック - **ランタイム**: Node.js 22 - **フレームワーク**: Express.js - **ストレージ**: ファイルシステム(Markdown + JSON) - **認証**: JWT(jsonwebtoken) - **セキュリティ**: Helmet(CSP)、express-rate-limit ### ディレクトリ構造 ``` server/ index.js # Express エントリ、ミドルウェアチェーン(固定順序) db.js # ファイルベース DB コア(読み書き/キュー/キャッシュ) routes/ docs.js # 公開: GET /docs, GET /docs/:slug auth.js # POST /login, POST /logout, GET /me captcha.js # キャプチャ生成/検証 meta.js # GET /categories, GET /tags geo.js # llms.txt, sitemap.xml, manifest llm.js # AI コンテンツ分析/生成 media.js # ファイルアップロード/ダウンロード config.js # サイト設定 versions.js # ドキュメントバージョン履歴 admin/ # 保護された管理ルート index.js # すべての管理サブルートをマウント docs.js # CRUD + 並べ替え drafts.js # ドラフトパイプライン categories.js, tags.js, feedback.js geo.js, stats.js, crawler-block.js guestbook.js, users.js middleware/ auth.js # JWT 検証、requireAuth、requireRole csrf.js # CSRF 保護(double-submit cookie) rateLimiter.js crawlerTracker.js utils/ logger.js # pino 構造化 JSON ログ promptGuard.js # LLM プロンプトインジェクション検出 path.js # パストラバーサル防止 ``` ### ミドルウェアチェーン(固定順序) ``` Helmet → CORS → JSON パーサー → rateLimiter → crawlerTracker → URL 重複排除 → ログ → CSRF → CSRF Cookie リフレッシュ → authRoutes → captchaRoutes → versionsRoutes → docsRoutes → metaRoutes → geoRoutes → llmRoutes → configRoutes → mediaRoutes → adminRoutes(requireAuth + requireRole + requirePasswordChange) ``` ::: warning ミドルウェアの登録順序は重要です。認証ルート(login/logout)は管理ルートの前に登録する必要があります。否则、ログインエンドポイントが認証ミドルウェア by 拦截されます。 ::: ## ファイルストレージ設計 ### ストレージ構造 ``` data/ docs/{lang}/*.md # Markdown ドキュメント(zh/en/jp) drafts/{lang}/*.md # ドラフト(AI レビューパイプライン) geo-wiki.json # カテゴリ/タグ/ユーザー/フィードバック設定 media-meta.json # アップローダー情報 history/{lang}/*.json # ドキュメントバージョン履歴 crawler-visits.json # AI クローラー訪問ログ csrf-secret.txt # CSRF シークレット(自動生成) public/media/ # アップロードされたメディアファイル ``` ### 書き込みキュー すべてのファイル書き込みは `enqueueWrite()` を通じて直列化された Promise チェーンに入ります。書き込み操作は 5 秒のデバウンスでバッチ処理され、書き込み後自動的に `invalidateCache()` が呼び出されます。 **重要**: `fs.writeFileSync` を直接呼び出さず、常に `saveDoc()`、`saveDb()`、または `enqueueWrite()` を使用してください。 ### キャッシュメカニズム - キャッシュ有効期限: 60 秒(`CACHE_TTL_MS`) - すべての書き込みで自動無効化 - 手動無効化サポート: `invalidateCache()` ## セキュリティアーキテクチャ ### 認証フロー ``` ユーザーログイン → パスワード検証 → JWT 生成 → httpOnly Cookie 設定 ↓ API リクエスト → Cookie 抽出 → JWT 検証 → ロールチェック → パスワード変更ステータスチェック ``` ### CSRF 保護 Double-Submit Cookie HMAC メカニズム: 1. サーバーがランダムシークレットを生成しファイルに保存 2. シークレットを Cookie とレスポンスヘッダーの両方に書き込み 3. クライアントが各リクエストでヘッダーにシークレットを返送 4. サーバーが HMAC 署名を検証 ### CSP ポリシー Nonce ベースの Content Security Policy: - 各リクエストで一意の Nonce を生成 - 正しい Nonce を持つスクリプトのみ実行を許可 - MutationObserver を通じた動的 CSS への Nonce 動的注入 ## API 設計 ### 公開 API すべての公開エンドポイントは `/api/v1/` に位置し、認証不要: | メソッド | エンドポイント | 説明 | |---------|---------------|------| | GET | `/api/v1/docs` | ドキュメントリスト(ページネーション、フィルタリング可能) | | GET | `/api/v1/docs/search` | 全文検索 | | GET | `/api/v1/docs/:slug` | 単一ドキュメント詳細 | | GET | `/api/v1/categories` | カテゴリスト | | GET | `/api/v1/tags` | タグリスト | | GET | `/api/v1/config` | 公開サイト設定 | | GET | `/api/v1/llms.txt` | AI クローラーデータ | | GET | `/api/v1/geo/sitemap.xml` | XML サイトマップ | ### 管理 API 認証とロール認可が必要: | メソッド | エンドポイント | 説明 | |---------|---------------|------| | POST | `/api/v1/auth/login` | ログイン | | POST | `/api/v1/auth/logout` | ログアウト | | GET | `/api/v1/auth/me` | 現在のユーザー情報 | | CRUD | `/api/v1/admin/docs` | ドキュメント管理 | | PUT | `/api/v1/admin/docs/reorder` | ドキュメント並べ替え | | CRUD | `/api/v1/admin/categories` | カテゴリ管理 | | CRUD | `/api/v1/admin/tags` | タグ管理 | | POST | `/api/v1/media/upload` | ファイルアップロード | | POST | `/api/v1/admin/geo/rebuild` | GEO ファイル再生成 | ### レスポンス形式 ```json // 成功 { "success": true, "data": { ... } } // ページネーション { "success": true, "data": [...], "pagination": { "page": 1, "limit": 20, "total": 42 } } // エラー { "success": false, "message": "Not found" } ``` ## デプロイアーキテクチャ ### Docker マルチステージビルド ``` ステージ 1: フロントエンドビルド Node.js 22 → npm install → npm run build → dist/ ステージ 2: 本番ランタイム Node.js 22 → Express.js API + Nginx 静的ファイル ``` ### 環境変数 主要な設定項目: | 変数 | 説明 | デフォルト | |------|------|-----------| | `PORT` | サーバーポート | 3002 | | `JWT_SECRET` | JWT シークレット(必須) | - | | `CORS_ORIGINS` | 許可された CORS オリジン | - | | `RATE_LIMIT_*` | レート制限設定 | 300/min | ```