# インフラ構成図

## 全体構成図

```mermaid
flowchart TB
    subgraph Clients["クライアント層"]
        WEB["Web Browser<br/>(Chrome, Firefox, Safari)"]
        DESKTOP["Desktop App<br/>(Electron)"]
        MOBILE["Mobile Browser<br/>(PWA対応)"]
    end

    subgraph SyncServer["Sync Server (Node.js)"]
        EXPRESS["Express.js<br/>Application"]

        subgraph Routes["APIルート"]
            SYNC["/sync<br/>データ同期"]
            ACCOUNT["/account<br/>認証管理"]
            ADMIN["/admin<br/>管理機能"]
            HEALTH["/health<br/>ヘルスチェック"]
            SECRETS["/secret<br/>シークレット管理"]
        end

        subgraph BankRoutes["銀行連携ルート"]
            GOCARDLESS["/gocardless<br/>欧州銀行連携"]
            SIMPLEFIN["/simplefin<br/>米国銀行連携"]
            PLUGGYAI["/pluggyai<br/>ブラジル銀行連携"]
        end

        subgraph AuthRoutes["認証ルート"]
            OPENID["/openid<br/>OpenID Connect"]
        end
    end

    subgraph Storage["ストレージ層"]
        subgraph DataDir["/data"]
            ACCOUNT_DB["account.sqlite<br/>(認証・ファイル管理)"]
            USER_FILES["user-files/<br/>(予算ファイル)"]
            SERVER_FILES["server-files/<br/>(サーバー設定)"]
        end
    end

    subgraph ExternalServices["外部サービス"]
        GOCARDLESS_API["GoCardless API<br/>(Nordigen)"]
        SIMPLEFIN_API["SimpleFIN API"]
        PLUGGYAI_API["Pluggy.ai API"]
        OIDC_PROVIDER["OpenID Provider<br/>(Keycloak, Auth0等)"]
    end

    WEB --> EXPRESS
    DESKTOP --> EXPRESS
    MOBILE --> EXPRESS

    EXPRESS --> Routes
    EXPRESS --> BankRoutes
    EXPRESS --> AuthRoutes

    SYNC --> ACCOUNT_DB
    SYNC --> USER_FILES
    ACCOUNT --> ACCOUNT_DB
    SECRETS --> ACCOUNT_DB
    ADMIN --> ACCOUNT_DB

    GOCARDLESS --> GOCARDLESS_API
    SIMPLEFIN --> SIMPLEFIN_API
    PLUGGYAI --> PLUGGYAI_API
    OPENID --> OIDC_PROVIDER
```

## デプロイメント構成図

```mermaid
flowchart TB
    subgraph Internet["インターネット"]
        USER["ユーザー"]
    end

    subgraph HostMachine["ホストマシン"]
        subgraph Docker["Docker環境"]
            ACTUAL["actual-server<br/>コンテナ<br/>:5006"]
        end

        subgraph Volumes["永続化ボリューム"]
            DATA["./actual-data<br/>/data"]
        end
    end

    subgraph OptionalProxy["オプション: リバースプロキシ"]
        NGINX["Nginx / Caddy<br/>:443 (HTTPS)"]
    end

    USER --> NGINX
    NGINX --> |"HTTP :5006"| ACTUAL
    USER -.-> |"Direct :5006"| ACTUAL
    ACTUAL --> DATA
```

## データベース構成図

```mermaid
erDiagram
    auth {
        TEXT method PK
        TEXT extra_data
        TEXT display_name
        INTEGER active
    }

    sessions {
        TEXT token PK
        INTEGER expires_at
        TEXT user_id
        TEXT auth_method
    }

    users {
        TEXT id PK
        TEXT user_name
        TEXT display_name
        TEXT role
        INTEGER enabled
        INTEGER owner
    }

    files {
        TEXT id PK
        TEXT group_id
        SMALLINT sync_version
        TEXT encrypt_meta
        TEXT encrypt_keyid
        TEXT encrypt_salt
        TEXT encrypt_test
        BOOLEAN deleted
        TEXT name
        TEXT owner
    }

    user_access {
        TEXT user_id PK
        TEXT file_id PK
    }

    secrets {
        TEXT name PK
        TEXT value
    }

    server_prefs {
        TEXT key PK
        TEXT value
    }

    users ||--o{ sessions : "has"
    users ||--o{ user_access : "has"
    files ||--o{ user_access : "accessed_by"
```

## 同期データフロー図

```mermaid
sequenceDiagram
    participant Client as クライアント
    participant Server as Sync Server
    participant DB as account.sqlite
    participant Files as user-files/

    Client->>Server: POST /sync/user-get-key
    Server->>DB: セッション検証
    DB-->>Server: ユーザー情報
    Server-->>Client: ファイルキー

    Client->>Server: POST /sync/sync
    Note over Client,Server: CRDT同期データ送信
    Server->>DB: メッセージ保存
    Server->>Files: ファイル更新
    Files-->>Server: 保存完了
    Server-->>Client: 同期結果
```

## 認証フロー図

### パスワード認証

```mermaid
sequenceDiagram
    participant Client as クライアント
    participant Server as Sync Server
    participant DB as account.sqlite

    Client->>Server: POST /account/login
    Note over Client,Server: {password: "xxx"}
    Server->>DB: パスワードハッシュ取得
    DB-->>Server: bcryptハッシュ
    Server->>Server: bcrypt.compare()
    alt 認証成功
        Server->>DB: セッショントークン作成
        Server-->>Client: {token: "xxx"}
    else 認証失敗
        Server-->>Client: {error: "invalid-password"}
    end
```

### OpenID Connect 認証

```mermaid
sequenceDiagram
    participant Client as クライアント
    participant Server as Sync Server
    participant OIDC as OpenID Provider

    Client->>Server: GET /openid/config
    Server-->>Client: OpenID設定情報

    Client->>OIDC: 認証リクエスト
    OIDC-->>Client: 認可コード

    Client->>Server: POST /openid/callback
    Note over Client,Server: {code: "xxx"}
    Server->>OIDC: トークン交換
    OIDC-->>Server: アクセストークン
    Server->>OIDC: ユーザー情報取得
    OIDC-->>Server: ユーザープロファイル
    Server-->>Client: セッショントークン
```

## 外部銀行連携フロー図

```mermaid
sequenceDiagram
    participant Client as クライアント
    participant Server as Sync Server
    participant Bank as 銀行API<br/>(GoCardless等)

    Client->>Server: POST /gocardless/create-web-token
    Server->>Bank: Requisition作成
    Bank-->>Server: リンクURL
    Server-->>Client: 銀行接続リンク

    Client->>Bank: 銀行認証
    Bank-->>Client: 認証完了

    Client->>Server: POST /gocardless/get-accounts
    Server->>Bank: 口座一覧取得
    Bank-->>Server: 口座情報
    Server-->>Client: 口座リスト

    Client->>Server: POST /gocardless/transactions
    Server->>Bank: 取引データ取得
    Bank-->>Server: 取引情報
    Server-->>Client: 取引リスト
```

## コンテナ構成図（開発環境）

```mermaid
flowchart TB
    subgraph DevEnvironment["開発環境"]
        subgraph DockerCompose["docker-compose.yml"]
            DEV_CONTAINER["actual-development<br/>Node.js 22<br/>:3001"]
        end

        subgraph Workspace["ワークスペース"]
            SOURCE["ソースコード<br/>/app"]
        end
    end

    subgraph Services["開発サービス"]
        VITE["Vite Dev Server<br/>:3001"]
        SYNC_DEV["Sync Server<br/>:5006"]
    end

    DEV_CONTAINER --> SOURCE
    SOURCE --> VITE
    SOURCE --> SYNC_DEV
```

## ネットワーク構成図

```mermaid
flowchart LR
    subgraph PublicNetwork["パブリックネットワーク"]
        INTERNET["インターネット"]
    end

    subgraph DMZ["DMZ (オプション)"]
        LB["ロードバランサー<br/>/ リバースプロキシ"]
    end

    subgraph PrivateNetwork["プライベートネットワーク"]
        subgraph TrustedProxies["信頼されるプロキシ範囲"]
            PROXY1["10.0.0.0/8"]
            PROXY2["172.16.0.0/12"]
            PROXY3["192.168.0.0/16"]
        end

        ACTUAL_SERVER["Actual Server<br/>:5006"]
    end

    INTERNET --> LB
    LB --> ACTUAL_SERVER
    PROXY1 -.-> ACTUAL_SERVER
    PROXY2 -.-> ACTUAL_SERVER
    PROXY3 -.-> ACTUAL_SERVER
```
