# 機能設計書 1-サーバー接続管理

## 概要

本ドキュメントは、InvenTreeモバイルアプリにおけるサーバー接続管理機能の設計を記載する。この機能はInvenTreeサーバーへの接続・認証を管理し、トークンベース認証を使用してユーザープロファイルを保存・切り替え可能にする。

### 本機能の処理概要

InvenTreeサーバーへの接続を確立し、認証状態を管理する機能である。ユーザーが選択したサーバープロファイルに基づいてREST APIエンドポイントに接続し、トークンベース認証を実行する。

**業務上の目的・背景**：在庫管理システムInvenTreeを活用する業務において、モバイルデバイスからサーバーにアクセスする必要がある。複数の環境（本番、開発、デモ等）を切り替えて使用するケースも多く、セキュアかつ柔軟な接続管理が求められる。本機能により、ユーザーは複数のサーバーへの接続を一元管理でき、業務効率が向上する。

**機能の利用シーン**：アプリ起動時の自動接続、手動でのサーバー選択・切り替え、接続エラー発生時の再接続、新規サーバー登録後の初回接続などで利用される。

**主要な処理内容**：
1. サーバーAPIエンドポイントへの疎通確認（api/エンドポイント）
2. 認証トークンの検証（user/me/エンドポイント）
3. ユーザー権限情報の取得（user/roles/エンドポイント）
4. プラグイン情報の取得
5. 接続状態の管理とコールバック通知
6. 定期的な通知カウンター更新

**関連システム・外部連携**：InvenTree REST API（バージョン100以上が必要）、Sentryエラー報告システム

**権限による制御**：サーバー接続後、ユーザーのロール（roles）とパーミッション（permissions）がAPIから取得され、各機能の利用可否が制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ホーム画面 | 主画面 | サーバー接続状態の表示、未接続時の接続ステータスウィジェット表示 |
| 7 | サーバー選択画面 | 参照画面 | プロファイル選択時のサーバー接続処理 |
| 9 | ログイン画面 | 参照画面 | ログイン成功時のサーバー接続確立 |

## 機能種別

データ連携 / 認証処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| profile | UserProfile | Yes | 接続対象のサーバープロファイル | null不可、server URLが必須 |
| server | String | Yes | サーバーのベースURL | http://またはhttps://で開始、末尾スラッシュは自動付与 |
| token | String | No | 認証トークン | 空の場合はログイン画面へ遷移が必要 |

### 入力データソース

- ローカルデータベース（sembast）に保存されたユーザープロファイル
- ログイン画面から取得した認証トークン

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| _connected | bool | 接続成功フラグ |
| serverInfo | Map<String, dynamic> | サーバー情報（バージョン、インスタンス名等） |
| userInfo | Map<String, dynamic> | 認証ユーザー情報 |
| roles | Map<String, dynamic> | ユーザーロール情報 |
| permissions | Map<String, dynamic> | ユーザーパーミッション情報 |

### 出力先

- InvenTreeAPIシングルトンインスタンスの状態
- 接続状態変更コールバックへの通知

## 処理フロー

### 処理シーケンス

```
1. connectToServer(UserProfile)呼び出し
   └─ 既存接続の切断（disconnectFromServer）

2. プロファイル設定
   └─ profile変数への保存

3. サーバー疎通確認（_checkServer）
   └─ api/エンドポイントへGETリクエスト
   └─ サーバーバージョン・APIバージョン確認
   └─ 最小APIバージョン（100）との比較

4. 認証確認（_checkAuth）
   └─ user/me/エンドポイントへGETリクエスト
   └─ トークンの有効性確認
   └─ ユーザー情報の取得

5. 権限情報取得（_fetchRoles）
   └─ user/roles/エンドポイントへGETリクエスト
   └─ ロールとパーミッションの保存

6. プラグイン情報取得（_fetchPlugins）
   └─ 有効なプラグイン一覧の取得

7. 接続完了処理
   └─ _connectedフラグをtrueに設定
   └─ コールバック関数の実行
   └─ 通知タイマーの開始
```

### フローチャート

```mermaid
flowchart TD
    A[connectToServer開始] --> B[既存接続を切断]
    B --> C[プロファイル設定]
    C --> D{トークン有り?}
    D -->|No| E[接続失敗]
    D -->|Yes| F[サーバー疎通確認]
    F --> G{API応答OK?}
    G -->|No| H[サーバーエラー表示]
    H --> E
    G -->|Yes| I{APIバージョン確認}
    I -->|古い| J[バージョンエラー表示]
    J --> E
    I -->|OK| K[認証確認]
    K --> L{認証成功?}
    L -->|No| M[トークン無効化]
    M --> E
    L -->|Yes| N[権限情報取得]
    N --> O[プラグイン情報取得]
    O --> P[接続完了]
    P --> Q[コールバック通知]
    Q --> R[通知タイマー開始]
    R --> S[終了]
    E --> S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 最小APIバージョン | サーバーAPIバージョンは100以上が必要 | サーバー接続時 |
| BR-02 | トークン必須 | 認証トークンがない場合は接続不可 | _checkAuth実行時 |
| BR-03 | 証明書検証 | strictHttps設定に基づきSSL証明書を検証 | HTTPS接続時 |
| BR-04 | 通知更新間隔 | 60秒ごとに通知カウンターを更新 | 接続中 |

### 計算ロジック

該当なし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| プロファイル更新 | profiles | UPDATE | トークン無効化時にトークンをクリア |

### テーブル別操作詳細

#### profiles（sembast store）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | token | "" (空文字) | 認証失敗時にトークンを無効化 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | SocketException | サーバー接続拒否 | connectionRefusedメッセージ表示 |
| - | TimeoutException | 接続タイムアウト（10秒） | タイムアウトエラー表示 |
| - | HandshakeException | SSL証明書エラー | serverCertificateErrorメッセージ表示 |
| - | CertificateException | SSL証明書無効 | serverCertificateErrorメッセージ表示 |
| 401/403 | 認証エラー | トークン無効または期限切れ | トークンクリア、再ログイン促進 |
| 500+ | サーバーエラー | サーバー内部エラー | Sentryへ報告、エラー表示 |

### リトライ仕様

- 自動リトライなし
- ユーザーによる手動再接続が必要

## トランザクション仕様

- 各APIリクエストは独立して実行
- ロールバック対象の処理なし
- 接続失敗時は状態をリセット（disconnectFromServer相当）

## パフォーマンス要件

- 接続タイムアウト: 10秒
- APIリクエストタイムアウト: 10秒
- 通知更新間隔: 60秒

## セキュリティ考慮事項

- トークンは端末内のsembastデータベースに保存
- HTTPS通信を推奨（strictHttps設定で強制可能）
- 認証ヘッダー: `Token {token}` 形式
- 自己署名証明書への対応オプションあり

## 備考

- InvenTreeAPIはシングルトンパターンで実装
- 接続状態の変更はコールバック関数で通知
- 複数のプロファイルを登録可能だが、同時接続は1つのみ

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、サーバー接続に使用されるデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user_profile.dart | `lib/user_profile.dart` | UserProfileクラスの構造（name, server, token, selected） |
| 1-2 | api.dart | `lib/api.dart` | APIResponseクラス（35-110行目）のレスポンス構造 |

**読解のコツ**: UserProfileはsembastのJSONシリアライズに対応しており、toJson/fromJsonメソッドでDB保存される。

#### Step 2: エントリーポイントを理解する

処理の起点となるAPI接続メソッドを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | api.dart | `lib/api.dart` | connectToServerメソッド（656-701行目）が公開API |

**主要処理フロー**:
1. **656-658行目**: disconnectFromServerで既存接続を切断
2. **660-668行目**: プロファイルのnullチェック
3. **674-679行目**: _connectToServerで実際の接続処理
4. **681-694行目**: 接続成功時の通知タイマー開始

#### Step 3: 内部接続処理を理解する

_connectToServerメソッドの詳細な処理フローを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | api.dart | `lib/api.dart` | _connectToServerメソッド（412-447行目） |
| 3-2 | api.dart | `lib/api.dart` | _checkServerメソッド（453-515行目）サーバー疎通確認 |
| 3-3 | api.dart | `lib/api.dart` | _checkAuthメソッド（521-541行目）認証確認 |
| 3-4 | api.dart | `lib/api.dart` | _fetchRolesメソッド（706-736行目）権限取得 |
| 3-5 | api.dart | `lib/api.dart` | _fetchPluginsメソッド（739-757行目）プラグイン取得 |

**主要処理フロー**:
- **476行目**: api/エンドポイントへのGETリクエスト
- **488-510行目**: APIバージョンチェックと最小バージョン検証
- **526行目**: user/me/エンドポイントで認証確認
- **711行目**: user/roles/エンドポイントで権限取得

#### Step 4: HTTP通信層を理解する

実際のHTTP通信処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | api.dart | `lib/api.dart` | apiRequestメソッド（1208-1301行目）リクエスト生成 |
| 4-2 | api.dart | `lib/api.dart` | completeRequestメソッド（1306-1396行目）レスポンス処理 |
| 4-3 | api.dart | `lib/api.dart` | defaultHeadersメソッド（1511-1523行目）認証ヘッダー |

**主要処理フロー**:
- **1177-1199行目**: HTTPクライアント生成と証明書コールバック
- **1514-1516行目**: Tokenヘッダーの設定
- **1330-1396行目**: レスポンスのJSONパースとエラーハンドリング

### プログラム呼び出し階層図

```
connectToServer(UserProfile)
    │
    ├─ disconnectFromServer()
    │      └─ _connectionStatusChanged()
    │
    └─ _connectToServer()
           ├─ _checkServer()
           │      └─ get("") → apiRequest() → completeRequest()
           │
           ├─ _checkAuth()
           │      └─ get("user/me/") → apiRequest() → completeRequest()
           │
           ├─ _fetchRoles()
           │      └─ get("user/roles/") → apiRequest() → completeRequest()
           │
           └─ _fetchPlugins()
                  └─ InvenTreePlugin().list()
```

### データフロー図

```
[入力]               [処理]                    [出力]

UserProfile ───▶ connectToServer ───▶ _connected=true
    │                    │                    │
    ├─ server           ├─ API検証            ├─ serverInfo
    ├─ token            ├─ 認証確認            ├─ userInfo
    └─ name             ├─ 権限取得            ├─ roles
                        └─ プラグイン取得       └─ permissions
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| api.dart | `lib/api.dart` | ソース | API通信の中核クラス（InvenTreeAPI） |
| user_profile.dart | `lib/user_profile.dart` | ソース | ユーザープロファイルデータモデルとDB管理 |
| preferences.dart | `lib/preferences.dart` | ソース | アプリ設定の管理（strictHttps等） |
| select_server.dart | `lib/settings/select_server.dart` | ソース | サーバー選択画面UI |
| login.dart | `lib/settings/login.dart` | ソース | ログイン画面UI |
| sentry.dart | `lib/inventree/sentry.dart` | ソース | エラー報告機能 |
| snacks.dart | `lib/widget/snacks.dart` | ソース | 通知メッセージ表示 |
