NemakiWare 3.1.0 のシステムアーキテクチャ概要です。
システム構成図
コンポーネント説明
データフロー
RAG パイプライン
認証フロー
ディレクトリ構成
データベース設計
┌─────────────────────────────────────────────────────────────────────┐
│ NemakiWare System │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Core (Tomcat 11.0 + Java 21) │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │
│ │ │ React SPA │ │ CMIS Server │ │ REST API │ │ │
│ │ │ (Vite 7) │ │ (OpenCMIS) │ │ (JAX-RS) │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ - Ant Design│ │ - AtomPub │ │ - User/Group │ │ │
│ │ │ - TypeScript│ │ - Browser │ │ - Auth Token │ │ │
│ │ │ - i18n │ │ - WSDL │ │ - Archive │ │ │
│ │ └──────────────┘ └──────┬───────┘ │ - Type Mgmt │ │ │
│ │ │ │ - Cloud Sync │ │ │
│ │ ┌────────────────────────┼───────────┴──────────────────┐ │ │
│ │ │ Spring Service Layer │ │ │
│ │ │ │ │ │
│ │ │ ObjectService / RepositoryService / AclService │ │ │
│ │ │ DiscoveryService / NavigationService / PolicyService │ │ │
│ │ │ CloudAuthService / DirectorySyncService / RAGService │ │ │
│ │ └───────────┬────────────────────────┬───────────────────┘ │ │
│ │ │ │ │ │
│ │ ┌───────────▼──────────┐ ┌─────────▼────────────────┐ │ │
│ │ │ DAO Layer │ │ Cache (EhCache) │ │ │
│ │ │ (CouchDB impl) │ │ - Content Cache │ │ │
│ │ │ │ │ - ACL Cache │ │ │
│ │ └───────────┬──────────┘ │ - Type Cache │ │ │
│ │ │ └──────────────────────────┘ │ │
│ └──────────────┼────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────▼──────┐ ┌──────────────┐ ┌───────────────────┐ │
│ │ CouchDB 3.x │ │ Solr 9.x │ │ TEI Server │ │
│ │ │ │ │ │ (HuggingFace) │ │
│ │ - bedroom (docs) │ │ - Full-text │ │ │ │
│ │ - bedroom_closet │ │ - Solr Cell │ │ - multilingual │ │
│ │ - canopy │ │ - Tika 2.9 │ │ -e5-large │ │
│ │ - nemaki_conf │ │ - Dense │ │ - 1024 dim │ │
│ │ │ │ Vector │ │ - CPU/GPU │ │
│ └──────────────────────┘ └──────────────┘ └───────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────┘
docker-compose-simple.yml
│
├── couchdb (:5984) ── CouchDB 3.3.3
├── solr (:8983) ── カスタム Solr 9.x
├── core (:8080) ── Tomcat 11.0 + Core WAR
│ depends_on: couchdb (healthy), solr (healthy)
│
└── [profile: rag]
└── tei (:8081) ── HuggingFace TEI cpu-1.6
Core (CMIS サーバー + React UI)
NemakiWare のメインコンポーネント。Tomcat 11.0 上で動作する WAR アプリケーション。
レイヤー
技術
役割
UI
React 19, TypeScript, Vite 7, Ant Design 5
ブラウザベースの管理インターフェース
CMIS Binding
Apache Chemistry OpenCMIS 1.1.0
CMIS 1.1 プロトコル実装 (AtomPub, Browser, WSDL)
REST API
JAX-RS (Jersey)
ユーザー管理、認証、アーカイブ等の拡張 API
Service
Spring Framework 7
ビジネスロジック (CMIS操作、権限、検索、同期)
DAO
CouchDB クライアント (Ektorp)
データアクセス抽象化
Cache
EhCache 3
コンテンツ・ACL・タイプ定義のキャッシュ
ドキュメント指向 NoSQL データベース。NemakiWare の全データを格納。
データベース
用途
bedroom
メインドキュメントリポジトリ
bedroom_closet
bedroom のアーカイブ(削除されたドキュメント)
canopy
標準リポジトリ(初期作成・UIからは非表示)
canopy_closet
canopy のアーカイブ
nemaki_conf
システム設定
Apache Solr 9.x ベースの全文検索エンジン。
Solr Cell (ExtractingRequestHandler + Tika 2.9): PDF, Office 等のテキスト抽出
DenseVector : RAG 用ベクトルフィールド(1024次元)
コアごとにリポジトリのインデックスを管理
TEI (Text Embeddings Inference)
Hugging Face のベクトル埋め込みサーバー。RAG セマンティック検索に使用。
モデル : intfloat/multilingual-e5-large (1024次元)
用途 : ドキュメントチャンクのベクトル化、検索クエリのベクトル化
デプロイ : Docker Compose rag プロファイルで有効化
Client (React UI / CMIS Client)
│
│ CMIS createDocument (Browser Binding POST)
▼
Core: NemakiBrowserBindingServlet
│
▼
Core: ObjectServiceImpl.createDocument()
│
├──▶ CouchDB: ドキュメントメタデータ保存
│ (cmis:objectId, cmis:name, properties, ACL)
│
├──▶ CouchDB: コンテンツストリーム保存
│ (attachmentとしてバイナリ格納)
│
├──▶ Solr: インデックス更新
│ (メタデータ + Tika によるテキスト抽出)
│
└──▶ [RAG 有効時] TEI: ベクトル埋め込み生成
(チャンク分割 → TEI API → Solr DenseVector 格納)
Client: 検索クエリ
│
▼
Core: DiscoveryServiceImpl.query()
│
├──▶ [通常検索] Solr: 全文検索 (CMIS SQL → Solr Query)
│ 結果: objectId のリスト
│
└──▶ [RAG 検索] TEI: クエリベクトル化
│
▼
Solr: ベクトル類似度検索 (kNN)
結果: objectId + スコアのリスト
│
▼
Core: CouchDB からドキュメントメタデータ取得
│
▼
Core: 権限チェック (ACL 評価)
│
▼
Client: 検索結果
Document Upload
│
▼
Content Stream (PDF, Word, Excel, etc.)
│
▼
テキスト抽出 (Tika / Solr Cell)
│
▼
チャンク分割
├── max_tokens: 200
├── overlap_tokens: 50
└── min_tokens: 50
│
▼
TEI API: /embed (バッチ処理)
├── batch_size: 32
└── model: intfloat/multilingual-e5-large
│
▼
1024次元ベクトル生成
│
▼
Solr DenseVector フィールドに格納
└── チャンクごとに objectId + chunk_index + vector
ユーザー検索クエリ
│
▼
TEI API: /embed (クエリベクトル化)
│
▼
Solr kNN 検索
├── topK: 10
└── similarity_threshold: 0.7
│
▼
類似チャンクのリスト (objectId + score)
│
▼
重複除去 + ドキュメント単位に集約
│
▼
ACL フィルタリング (権限のないドキュメントを除外)
│
▼
検索結果
カテゴリ
MIME タイプ
テキスト
text/plain, text/html, text/xml
PDF
application/pdf
Word
application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document
Excel
application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
PowerPoint
application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation
方式
設定キー
IdP
Basic 認証
(デフォルト)
NemakiWare 内蔵
Auth Token
capability.extended.auth.token=true
NemakiWare 内蔵
Google OIDC
cloud.auth.google.enabled=true
Google (直接)
Microsoft OIDC
cloud.auth.microsoft.enabled=true
Microsoft Entra ID (直接)
Keycloak OIDC
oidc.enabled=true
Keycloak
Keycloak SAML
saml.enabled=true
Keycloak
Google OIDC 認証フロー(Keycloakなし)
ブラウザ (React UI)
│
│ 1. 「Googleでログイン」クリック
▼
Google OAuth 2.0 認証画面
│
│ 2. ユーザーが Google アカウントで認証
▼
Google → NemakiWare コールバック
│ Authorization Code 付きリダイレクト
│ /core/rest/repo/bedroom/authtoken/oidc/callback
▼
Core: AuthTokenResource.oidcCallback()
│
│ 3. Authorization Code → ID Token 交換
│ (Google Token Endpoint へサーバーサイドリクエスト)
▼
Core: CloudAuthService.verifyGoogleIdToken()
│
│ 4. ID Token 検証
│ - 署名検証 (Google 公開鍵)
│ - iss, aud, exp チェック
▼
Core: ユーザー検索 / 自動作成
│ email をキーにユーザーを検索
│ 存在しない場合は自動作成 (isAutoCreateUser=true)
▼
Core: NemakiWare Auth Token 発行
│
▼
ブラウザ: Auth Token を Cookie に保存
│
▼
以降の API リクエストは Auth Token で認証
ブラウザ
│
│ POST /core/rest/repo/{repoId}/authtoken
│ Basic Auth: admin:admin
▼
Core: AuthTokenResource.createToken()
│ - BCrypt パスワード検証
│ - JWT Auth Token 生成 (有効期限: 24h)
▼
ブラウザ: Auth Token を Cookie/Header に設定
│
│ 以降のリクエスト
│ Authorization: Bearer <auth-token>
│ または Cookie: NemakiWareToken=<auth-token>
▼
Core: NemakiAuthCallContextHandler
│ - Auth Token 検証
│ - ユーザー情報取得
▼
CMIS サービス実行
SAML 認証フロー(Keycloak SAML 2.0)
ブラウザ: SAML ログインボタンクリック
│
│ SAMLService.initiateLogin()
│ SAMLRequest (DEFLATE + Base64) + RelayState
▼
IdP (Keycloak): SAML SSO URL
│ ユーザー認証 (ログインフォーム)
▼
IdP → ブラウザ: HTML 自動送信フォーム (POST binding)
│ SAMLResponse (署名付き Assertion)
│ POST /core/saml/acs
▼
Core: SamlAcsServlet.doPost()
│ - SAMLResponse/RelayState を sessionStorage に保存する
│ JavaScript を含む HTML を返却
│ - /core/ui/saml-callback.html にリダイレクト
▼
ブラウザ: React SPA (Login.tsx)
│ sessionStorage から SAMLResponse を読み取り
│ POST /core/rest/repo/{repoId}/authtoken/saml/convert
▼
Core: AuthTokenResource.convertSAMLToken()
│ - Base64 デコード + オプショナル DEFLATE 解凍
│ - XXE 安全 XML パーサー
│ - SamlSignatureVerifier: 署名検証 + ラッピング攻撃防御
│ - AudienceRestriction/Conditions 検証
│ - NameID からユーザー名抽出 → getOrCreateUser()
│ - Auth Token 生成
▼
ブラウザ: Auth Token を Cookie/localStorage に設定
--- SLO (Single Logout) ---
ブラウザ: ログアウトボタン
│ SAMLService.initiateLogout(username)
│ SAMLLogoutRequest (NameID 付き, DEFLATE + Base64)
▼
IdP (Keycloak): SAML SLO URL
│ IdP セッション終了
▼
ブラウザ: ログインページにリダイレクト
NemakiWare/
├── core/ # メイン CMIS サーバーモジュール (WAR)
│ ├── src/main/java/jp/aegif/nemaki/
│ │ ├── cmis/ # CMIS サーバー実装
│ │ │ ├── factory/ # CMIS サービスファクトリ
│ │ │ │ └── auth/ # 認証ハンドラ (Basic, Token, OIDC)
│ │ │ ├── service/ # CMIS サービス実装
│ │ │ │ └── impl/ # ObjectService, AclService 等
│ │ │ └── servlet/ # CMIS サーブレット定義
│ │ ├── rest/ # REST API エンドポイント
│ │ │ ├── AuthTokenResource.java # 認証トークン (SAML/OIDC変換含む)
│ │ │ ├── SamlAcsServlet.java # SAML POST binding ACS
│ │ │ ├── SamlSignatureVerifier.java # SAML署名検証 (XSW攻撃防御)
│ │ │ ├── UserResource.java
│ │ │ ├── GroupResource.java
│ │ │ └── TypeResource.java
│ │ ├── dao/ # データアクセス層
│ │ │ └── impl/couch/ # CouchDB 実装
│ │ ├── model/ # ドメインモデル
│ │ ├── businesslogic/ # ビジネスロジック
│ │ ├── util/ # ユーティリティ
│ │ ├── patch/ # DB マイグレーション
│ │ └── webhook/ # Webhook ディスパッチャー
│ │
│ ├── src/main/webapp/
│ │ ├── ui/ # React SPA フロントエンド
│ │ │ ├── src/
│ │ │ │ ├── components/ # React コンポーネント
│ │ │ │ ├── services/ # API サービス層
│ │ │ │ │ ├── auth.ts # 認証サービス
│ │ │ │ │ ├── cmis.ts # CMIS API クライアント
│ │ │ │ │ └── cloud-drive.ts # Cloud Drive 連携
│ │ │ │ ├── i18n/ # 国際化 (ja, en)
│ │ │ │ └── types/ # TypeScript 型定義
│ │ │ ├── tests/ # Playwright E2E テスト
│ │ │ ├── package.json
│ │ │ └── vite.config.ts
│ │ └── WEB-INF/
│ │ └── classes/ # Spring XML 設定ファイル
│ │
│ └── pom.xml
│
├── common/ # 共有ユーティリティ
├── solr/ # Solr 設定・カスタマイズ
├── docker/ # Docker Compose 構成
│ ├── docker-compose-simple.yml
│ ├── core/ # Core コンテナ設定
│ │ ├── Dockerfile.simple
│ │ ├── nemakiware.properties
│ │ └── repositories.yml
│ ├── solr/ # Solr コンテナ設定
│ └── secrets/ # シークレットファイル (Git 管理外)
├── lib/ # Jakarta EE 変換済みカスタム JAR
├── docs/ # ドキュメント
│ ├── ARCHITECTURE.md # 本ドキュメント
│ ├── AWS-DEPLOYMENT-GUIDE.md # AWS デプロイガイド
│ └── CLOUD_INTEGRATION.md # クラウド統合設定ガイド
└── qa-test.sh # QA 統合テストスクリプト
機能
パス
CMIS サービス実装
core/src/main/java/jp/aegif/nemaki/cmis/service/impl/
認証ハンドラ
core/src/main/java/jp/aegif/nemaki/cmis/factory/auth/
REST API
core/src/main/java/jp/aegif/nemaki/rest/
CouchDB DAO
core/src/main/java/jp/aegif/nemaki/dao/impl/couch/
ドメインモデル
core/src/main/java/jp/aegif/nemaki/model/
Spring 設定
core/src/main/webapp/WEB-INF/classes/*.xml
React コンポーネント
core/src/main/webapp/ui/src/components/
CMIS API クライアント
core/src/main/webapp/ui/src/services/cmis.ts
認証サービス
core/src/main/webapp/ui/src/services/auth.ts
i18n 翻訳
core/src/main/webapp/ui/src/i18n/locales/
アプリ設定
docker/core/nemakiware.properties
リポジトリ定義
docker/core/repositories.yml
CouchDB
├── bedroom # メインリポジトリ
│ ├── _design/repo # コンテンツクエリ用ビュー
│ ├── _design/user # ユーザー/グループ管理用ビュー
│ └── _design/change # 変更ログ用ビュー
│
├── bedroom_closet # アーカイブ(削除されたドキュメント)
├── canopy # 標準リポジトリ(UIからは非表示)
├── canopy_closet # canopy アーカイブ
└── nemaki_conf # システム設定
タイプ
説明
主要フィールド
cmis:document
CMIS ドキュメント
objectId, name, contentStream, versionSeries
cmis:folder
CMIS フォルダ
objectId, name, parentId
user
ユーザー
userId, name, password (BCrypt), email
group
グループ
groupId, name, members[]
type
タイプ定義
typeId, parentId, properties[]
change
変更ログ
changeType, objectId, changeTime
archive
アーカイブ
originalId, deletedTime, restorable
CMIS ネイティブ : すべてのデータ操作は CMIS 仕様に準拠
Repository パターン : DAO インターフェースによるデータアクセス抽象化
キャッシュ活用 : EhCache によるコンテンツ・ACL・タイプ定義のキャッシュ
非同期処理 : Solr インデックス更新、RAG ベクトル生成は非同期実行
自動初期化 : PatchService による DB マイグレーション・初期化の自動実行