# アーキテクチャ構成図

## システム全体構成図

```mermaid
graph TB
    subgraph "Client Layer"
        Browser["Web Browser"]
        AdminUI["Admin UI<br/>(React)"]
    end

    subgraph "Transport Layer"
        HTTP["HTTP/HTTPS<br/>(Express 5)"]
        WS["WebSocket<br/>(Socket.IO 4)"]
    end

    subgraph "Server - Etherpad Lite"
        subgraph "Presentation Layer"
            Express["Express Server<br/>(hooks/express.ts)"]
            SocketIO["Socket.IO Router<br/>(SocketIORouter.ts)"]
            Templates["EJS Templates<br/>(templates/)"]
            StaticFiles["Static Files<br/>(static/)"]
        end

        subgraph "Handler Layer"
            PadMsgHandler["PadMessageHandler"]
            APIHandler["APIHandler"]
            ImportHandler["ImportHandler"]
            ExportHandler["ExportHandler"]
        end

        subgraph "Application Layer"
            API["API Module<br/>(db/API.ts)"]
            Hooks["Hook System<br/>(pluginfw/hooks.ts)"]
            Plugins["Plugin Manager<br/>(pluginfw/plugins.ts)"]
        end

        subgraph "Domain Layer"
            Pad["Pad Model"]
            Author["AuthorManager"]
            Session["SessionManager"]
            Group["GroupManager"]
            Security["SecurityManager"]
            ReadOnly["ReadOnlyManager"]
        end

        subgraph "Infrastructure Layer"
            DB["Database<br/>(ueberdb2)"]
            SessionStore["SessionStore"]
            SecretRotator["SecretRotator"]
        end

        subgraph "Security Layer"
            WebAccess["WebAccess<br/>(webaccess.ts)"]
            OAuth2["OAuth2Provider"]
            OIDC["OIDCAdapter"]
        end
    end

    subgraph "External Systems"
        Database[(Database<br/>dirty/MySQL/PostgreSQL)]
        Abiword["Abiword"]
        LibreOffice["LibreOffice"]
        OIDCProvider["External OIDC Provider"]
    end

    Browser -->|HTTP| HTTP
    Browser -->|WebSocket| WS
    AdminUI -->|HTTP| HTTP
    AdminUI -->|WebSocket| WS

    HTTP --> Express
    WS --> SocketIO

    Express --> WebAccess
    Express --> Templates
    Express --> StaticFiles
    Express --> APIHandler
    Express --> ImportHandler
    Express --> ExportHandler

    SocketIO --> PadMsgHandler
    PadMsgHandler --> Hooks

    APIHandler --> API
    API --> Pad
    API --> Author
    API --> Session
    API --> Group

    PadMsgHandler --> Pad
    PadMsgHandler --> Author
    PadMsgHandler --> Security

    ImportHandler --> Pad
    ExportHandler --> Pad

    Pad --> DB
    Author --> DB
    Session --> SessionStore
    Group --> DB
    Security --> DB
    ReadOnly --> DB

    SessionStore --> DB
    SecretRotator --> DB

    WebAccess --> OAuth2
    WebAccess --> Security
    OAuth2 --> OIDC

    DB --> Database
    ImportHandler --> Abiword
    ImportHandler --> LibreOffice
    ExportHandler --> Abiword
    ExportHandler --> LibreOffice
    OAuth2 --> OIDCProvider
```

## レイヤー構成図

```mermaid
graph TB
    subgraph "Presentation Layer"
        P1["admin/ (React SPA)"]
        P2["ui/ (OIDC UI)"]
        P3["templates/ (EJS)"]
        P4["static/js/ (Client JS)"]
    end

    subgraph "Handler Layer"
        H1["PadMessageHandler"]
        H2["APIHandler"]
        H3["SocketIORouter"]
        H4["Import/ExportHandler"]
    end

    subgraph "Application Layer"
        A1["API.ts"]
        A2["hooks/"]
        A3["pluginfw/"]
    end

    subgraph "Domain Layer"
        D1["Pad.ts"]
        D2["AuthorManager.ts"]
        D3["SessionManager.ts"]
        D4["GroupManager.ts"]
        D5["PadManager.ts"]
        D6["SecurityManager.ts"]
    end

    subgraph "Infrastructure Layer"
        I1["DB.ts (ueberdb2)"]
        I2["SessionStore.ts"]
        I3["Utils (Abiword, LibreOffice)"]
    end

    subgraph "Security (Cross-cutting)"
        S1["webaccess.ts"]
        S2["OAuth2Provider.ts"]
        S3["SecretRotator.ts"]
    end

    P1 --> H2
    P2 --> S2
    P3 --> H1
    P4 --> H3

    H1 --> A1
    H2 --> A1
    H3 --> H1
    H4 --> D1

    A1 --> D1
    A1 --> D2
    A1 --> D3
    A1 --> D4
    A2 --> A3

    D1 --> I1
    D2 --> I1
    D3 --> I2
    D4 --> I1
    D5 --> I1
    D6 --> I1

    S1 --> D6
    S2 --> I1
    S3 --> I1
```

## Socket.IO メッセージフロー

```mermaid
sequenceDiagram
    participant Client as Browser Client
    participant Router as SocketIORouter
    participant Handler as PadMessageHandler
    participant Pad as Pad Model
    participant DB as Database

    Client->>Router: connect
    Router->>Handler: handleConnect()
    Handler-->>Client: connection established

    Client->>Router: message (CLIENT_READY)
    Router->>Handler: handleMessage()
    Handler->>Pad: getPad()
    Pad->>DB: get pad data
    DB-->>Pad: pad data
    Handler-->>Client: CLIENT_VARS (initial data)

    Client->>Router: message (USER_CHANGES)
    Router->>Handler: handleUserChanges()
    Handler->>Handler: rebase changeset
    Handler->>Pad: appendRevision()
    Pad->>DB: save revision
    Handler-->>Client: ACCEPT_COMMIT
    Handler->>Router: broadcast NEW_CHANGES
    Router-->>Client: NEW_CHANGES (to other clients)

    Client->>Router: disconnect
    Router->>Handler: handleDisconnect()
    Handler->>Router: broadcast USER_LEAVE
```

## データベーススキーマ（論理構造）

```mermaid
erDiagram
    PAD {
        string id PK
        json atext
        json pool
        int head
        int chatHead
        boolean publicStatus
        json savedRevisions
    }

    PAD_REVISION {
        string padId FK
        int revNum
        string changeset
        string author
        timestamp timestamp
        json pool "optional (key revision)"
        json atext "optional (key revision)"
    }

    PAD_CHAT {
        string padId FK
        int chatNum
        string text
        string authorId
        timestamp time
    }

    AUTHOR {
        string id PK
        string name
        string colorId
        json pads
    }

    GROUP {
        string id PK
        json pads
    }

    SESSION {
        string id PK
        string groupId
        string authorId
        timestamp validUntil
    }

    READONLY {
        string readOnlyId PK
        string padId
    }

    PAD ||--o{ PAD_REVISION : has
    PAD ||--o{ PAD_CHAT : has
    AUTHOR ||--o{ PAD_REVISION : writes
    AUTHOR ||--o{ PAD_CHAT : sends
    GROUP ||--o{ PAD : contains
    SESSION }o--|| GROUP : "belongs to"
    SESSION }o--|| AUTHOR : "belongs to"
    PAD ||--|| READONLY : "has"
```

## プラグインフックシステム

```mermaid
graph LR
    subgraph "Server Lifecycle"
        loadSettings["loadSettings"]
        createServer["createServer"]
        expressPreSession["expressPreSession"]
        expressConfigure["expressConfigure"]
        expressCreateServer["expressCreateServer"]
        shutdown["shutdown"]
    end

    subgraph "Pad Lifecycle"
        padDefaultContent["padDefaultContent"]
        padCreate["padCreate"]
        padLoad["padLoad"]
        padUpdate["padUpdate"]
        padRemove["padRemove"]
        padCopy["padCopy"]
    end

    subgraph "User/Session"
        userJoin["userJoin"]
        userLeave["userLeave"]
        clientVars["clientVars"]
        handleMessage["handleMessage"]
        handleMessageSecurity["handleMessageSecurity"]
    end

    subgraph "Authentication"
        preAuthorize["preAuthorize"]
        authenticate["authenticate"]
        authorize["authorize"]
        authnFailure["authnFailure"]
        authzFailure["authzFailure"]
    end

    subgraph "Chat"
        chatNewMessage["chatNewMessage"]
    end

    loadSettings --> createServer
    createServer --> expressPreSession
    expressPreSession --> expressConfigure
    expressConfigure --> expressCreateServer

    padCreate --> padLoad
    padLoad --> padUpdate
    padUpdate --> padRemove

    userJoin --> handleMessage
    handleMessage --> userLeave

    preAuthorize --> authenticate
    authenticate --> authorize
```

## コンポーネント配置図

```mermaid
graph TB
    subgraph "Container: Node.js Runtime"
        subgraph "Monorepo Packages"
            SRC["ep_etherpad-lite<br/>(src/)"]
            ADMIN["admin<br/>(React SPA)"]
            UI["ui<br/>(OIDC UI)"]
            BIN["bin<br/>(CLI Tools)"]
            DOC["doc<br/>(Documentation)"]
        end

        subgraph "Runtime Data"
            VAR["var/<br/>(dirty.db, etc.)"]
            PLUGINS["node_modules/<br/>(plugins: ep_*)"]
        end
    end

    subgraph "External Dependencies"
        NPM["npm Registry<br/>(plugins)"]
        PNPM["pnpm Store"]
    end

    SRC --> VAR
    SRC --> PLUGINS
    ADMIN --> SRC
    UI --> SRC
    BIN --> SRC
    PLUGINS --> NPM
    PLUGINS --> PNPM
```

## デプロイメント構成図（Docker）

```mermaid
graph TB
    subgraph "Docker Host"
        subgraph "etherpad-container"
            NODE["Node.js LTS Alpine"]
            PNPM["pnpm"]
            APP["Etherpad Application"]
            PORT["Port 9001"]
        end

        subgraph "Optional Containers"
            ABIWORD["Abiword<br/>(document conversion)"]
            SOFFICE["LibreOffice<br/>(document conversion)"]
        end

        subgraph "Database Container (optional)"
            MYSQL["MySQL"]
            POSTGRES["PostgreSQL"]
        end
    end

    subgraph "Volumes"
        DATA["Data Volume<br/>(var/)"]
        SETTINGS["Settings<br/>(settings.json)"]
        PLUGINS_VOL["Plugins<br/>(node_modules/ep_*)"]
    end

    CLIENT["Browser Client"] --> PORT
    APP --> DATA
    APP --> SETTINGS
    APP --> PLUGINS_VOL
    APP --> MYSQL
    APP --> POSTGRES
    APP --> ABIWORD
    APP --> SOFFICE
```
