技術アーキテクチャ
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 |
```