---
doc_id: account-identity-spec
title: Aile 帳號身份體系規格說明書
description: Aile Account、AppAccount、TenantEmployee、TenantContact、Scope、服務號成員與匿名轉實名流程規格，供開發團隊參考。
slug: /specifications/account-identity-spec
product: Aile
category: specification
audience:
  - developer
  - architect
  - qa
visibility: public
status: published
version: 1.0.0
owner: aile-platform
updated_at: 2026-06-13
tags:
  - Aile
  - Account
  - Identity
  - Tenant
  - 規格說明書
rendered_html: /rendered/specifications/account-identity-spec/
download: true
sidebar_position: 7
---

# Aile 帳號身份體系規格說明書

**版本：** v1.0  
**最後更新：** 2026-06-13  
**服務範圍：** `aile-service-account`、`aile-service-tenant`、`aile-service-room`  

---

## 1. 概述

Aile 的身份體系採用分層設計，以 **Account（帳號）** 為頂層統一身份，向下關聯 **AppAccount（應用帳號）**、**TenantEmployee（員工）**、**TenantContact（客戶/聯繫人）** 等租戶級身份。系統支援匿名訪客到實名用戶的平滑過渡，並透過 Scope 機制管理渠道級身份映射。

### 1.1 核心設計原則

| 原則 | 說明 |
|------|------|
| **Account 是統一身份錨點** | 所有租戶級身份（員工、客戶）都歸屬於一個 Account |
| **租戶隔離** | 同一 Account 在不同租戶中有獨立的 Employee 或 Contact 記錄 |
| **渠道多身份** | 同一 Account 可透過多個 channel+scopeId 訪問同一服務號 |
| **匿名可合併** | 匿名訪客的 Contact 資料可在實名登入後合併到實名 Account |

---

## 2. 身份層級總覽

```
┌─────────────────────────────────────────────────────────┐
│                     AccountModel                         │
│              (aile.account) — 頂層統一身份                 │
│  欄位: mobile, channel, status, isSystem, personRoomId   │
│  類型: Anonymous | NonRealName | RealName | System       │
└────────────┬──────────────┬──────────────────────────────┘
             │              │
      ┌──────▼──────┐  ┌───▼──────────────────────────┐
      │ AppAccount  │  │     AccountScopeModel         │
      │ Model       │  │  (aile.account.scope)         │
      │ (aile.      │  │  帳號在渠道上的 scope 映射      │
      │  account    │  │  accountId ↔ channel ↔ scopeId│
      │  .app)      │  └───────────────────────────────┘
      │ 應用帳號     │
      └─────────────┘

┌──────────────────────────────────────────────────────────┐
│                    租戶層 (Tenant)                         │
│                                                          │
│  ┌─────────────────────┐  ┌────────────────────────────┐ │
│  │ TenantEmployeeModel │  │   TenantContactModel       │ │
│  │ (aile.tenant.       │  │  (aile.tenant.contact)     │ │
│  │  employee)          │  │  客戶 / 聯繫人               │ │
│  │ 員工                 │  │  type: RealName |          │ │
│  │ joinType: Guarantor  │  │         Anonymous |        │ │
│  │         | Invitation │  │         Independent       │ │
│  └─────────┬───────────┘  └─────────────┬──────────────┘ │
│            │                             │                │
└────────────┼─────────────────────────────┼────────────────┘
             │                             │
      ┌──────▼──────┐              ┌───────▼──────────────┐
      │ServiceMember│              │  ServiceNumberScope   │
      │   Model     │              │       Model           │
      │ 服務號成員   │              │  服務號進線 scope      │
      │ privilege:  │              │  customerId ↔         │
      │ Owner /     │              │  serviceNumberId ↔    │
      │ Manager /   │              │  channel ↔ scopeId    │
      │ Common      │              │  ↔ roomId             │
      └─────────────┘              └───────────────────────┘
                                           │
                                   ┌───────▼──────────────┐
                                   │ServiceNumberRelation  │
                                   │       Model           │
                                   │  服務號訂閱關係         │
                                   │  customerId ↔         │
                                   │  serviceNumberId ↔    │
                                   │  accountId            │
                                   └───────────────────────┘
```

---

## 3. AccountModel（頂層帳號）

### 3.1 資料結構

MongoDB 集合：`aile.account`

```java
// aile-api/aile-account-api/.../model/AccountModel.java
@Document("aile.account")
public class AccountModel extends BaseModel {
    String mobile;        // 手機號碼
    String countryCode;   // 國碼
    Channel channel;      // 註冊渠道
    Status status;        // Enable / Disable（Saga 歸併可標記為 Deleted）
    Boolean isSystem;     // 是否為系統帳號
    String personRoomId;  // 個人聊天室 ID（系統級）
}
```

### 3.2 帳號類型（推導）

帳號類型透過 `AccountType.get(AccountModel)` 推導，非持久化欄位：

```java
// aile-api/aile-account-api/.../enums/AccountType.java
public enum AccountType {
    Anonymous,    // 匿名用戶（Channel.isAnonymous() == true）
    NonRealName,  // 未實名用戶（無手機號）
    RealName,     // 實名用戶（有手機號）
    System        // 系統用戶（isSystem == true）
}
```

### 3.3 登入方式

```java
// aile-api/aile-account-api/.../constant/LoginType.java
LINE(1),         // LINE 登入
THIRD(2),        // 第三方登入
OTP(3),          // OTP 登入
PWD(4),          // 密碼登入
ONCE_TOKEN(5),   // 一次性 Token 登入
DEVICE(6),       // 裝置登入
QRCODE(7),       // 掃描登入
ACCESS(8),       // 授權登入
SERVICE(9),      // 服務登入
AUTO(10),        // 自動登入
ANONYMOUS(11)    // 匿名登入
```

### 3.4 帳號服務

位置：`aile-service/aile-service-account/.../service/impl/AccountServiceImpl.java`

| 方法 | 說明 |
|------|------|
| `register(dto)` | 註冊新帳號（手機號 + 渠道） |
| `login(dto)` | 登入（支援多種登入方式） |
| `syncCreate(dto)` | 同步建立（供跨服務調用） |
| `update(dto)` | 更新帳號資訊 |

---

## 4. AppAccountModel（應用帳號）

### 4.1 資料結構

MongoDB 集合：`aile.account.app`

```java
// aile-api/aile-account-api/.../model/AppAccountModel.java
@Document("aile.account.app")
@CompoundIndexes({
    @CompoundIndex(name = "accountId_1_channel_1", def = "{'accountId': 1, 'channel': 1}"),
    @CompoundIndex(name = "accountId_1_channel_1_status_1", def = "{'accountId': 1, 'channel': 1, 'status': 1}"),
    @CompoundIndex(name = "accountId_1_updateTime_1", def = "{'accountId': 1, 'updateTime': 1}")
})
public class AppAccountModel extends BaseModel {
    String accountId;      // 關聯的 Account ID
    String name;           // 顯示名稱
    Integer age;           // 年齡
    Gender gender;         // 性別
    String birthday;       // 生日
    List<String> interests;// 興趣標籤
    Channel channel;       // 渠道
    String password;       // 密碼（加密）
    String avatarId;       // 頭像 ID
    Status status;         // Enable / Disable
    Boolean androidMute;   // Android 靜音
    Boolean iosMute;       // iOS 靜音
    Boolean pcMute;        // PC 靜音
    // ...
}
```

### 4.2 設計意圖

- **一個 Account 可有多個 AppAccount**：每個 `accountId + channel` 組合對應一個 AppAccount
- AppAccount 儲存該渠道下的個人資料（頭像、暱稱、靜音設定等）
- 與 AccountModel 的關係為 **多對一**

---

## 5. AccountScopeModel（帳號渠道 Scope）

### 5.1 資料結構

MongoDB 集合：`aile.account.scope`

```java
// aile-api/aile-account-api/.../model/AccountScopeModel.java
@Document("aile.account.scope")
@CompoundIndexes({
    @CompoundIndex(name = "scopeId_1_channel_1", def = "{'scopeId': 1, 'channel': 1}"),
    @CompoundIndex(name = "accountId_1_channel_1_scopeId_1", def = "{'accountId': 1, 'channel': 1, 'scopeId': 1}")
})
public class AccountScopeModel extends BaseModel {
    String scopeId;    // 渠道側唯一 ID（如 LINE userId）
    Channel channel;   // 渠道
    String accountId;  // 關聯的 Account ID
    String name;       // 渠道側顯示名稱
}
```

### 5.2 用途

AccountScopeModel 是 Account 層級的渠道映射，與 Tenant 層級的 `ServiceNumberScopeModel` 互補：

| 層級 | 模型 | 用途 |
|------|------|------|
| Account 層 | `AccountScopeModel` | Account ↔ channel ↔ scopeId（登入級） |
| Tenant 層 | `ServiceNumberScopeModel` | Contact ↔ serviceNumberId ↔ channel ↔ scopeId（服務號級） |

---

## 6. TenantEmployeeModel（員工）

### 6.1 資料結構

MongoDB 集合：`aile.tenant.employee`

```java
// aile-api/aile-tenant-api/.../model/TenantEmployeeModel.java
@Document("aile.tenant.employee")
public class TenantEmployeeModel extends BaseModel {
    String name;                // 姓名
    String avatarId;            // 頭像 ID
    String mood;                // 個性簽名
    Integer age;                // 年齡
    Gender gender;              // 性別
    String birthday;            // 生日
    Status status;              // Enable / Disable
    String accountId;           // 關聯的 Account ID
    String tenantId;            // 所屬租戶 ID
    Channel channel;            // 渠道
    String personRoomId;        // 個人聊天室 ID
    String systemRoomId;        // 系統聊天室 ID
    TenantJoinType joinType;    // 加入方式：Guarantor / Invitation
    String openId;              // 外部 OpenID
    Boolean isJoinAile;         // 是否已加入 Aile 生態
    Boolean isBindAile;         // 是否已綁定 Aile 生態
    Boolean isCollectInfo;      // 是否已收集資訊
    String homePagePicId;       // 主頁背景圖 ID
}
```

### 6.2 加入方式

```java
// aile-api/aile-tenant-api/.../enums/TenantJoinType.java
public enum TenantJoinType {
    Guarantor,   // 擔保人邀請
    Invitation   // 邀請碼加入
}
```

### 6.3 與 Account 的關係

- `accountId` 關聯 AccountModel
- 一個 Account 可以在多個 Tenant 中作為 Employee
- **同一 Account 在同一 Tenant 中只能有一條 Employee 記錄**

### 6.4 加入生態流程

```
Account 登入
  │
  └── TenantBindService.send(TenantBindDto)
        │
        ├── 向 Account 的個人聊天室發送「加入生態」卡片
        ├── Account 接受 → TenantBindService.collectInfo()
        │     ├── 建立 TenantEmployeeModel
        │     ├── isJoinAile = true
        │     └── isBindAile = true
        │
        └── TenantBindService.check()
              └── 檢查 Account 是否已加入該租戶
```

---

## 7. TenantContactModel（客戶 / 聯繫人）

### 7.1 資料結構

MongoDB 集合：`aile.tenant.contact`

```java
// aile-api/aile-tenant-api/.../model/TenantContactModel.java
@Document("aile.tenant.contact")
public class TenantContactModel extends BaseModel {
    // 基本資料
    String name;                // 姓名
    Integer age;
    Gender gender;
    String birthday;
    String phone;
    String email;
    // 公司資料
    String company;
    Boolean isAileCompany;
    String companyAddress;
    String companyPhone;
    String companyEmail;
    String companyDuty;
    String companyDepartment;
    // 其他
    BloodType bloodType;
    MaritalStatus maritalStatus;
    List<Language> languages;
    String interests;
    String alias;              // 備註名
    String description;        // 描述
    String businessCardId;     // 名片 ID
    String openId;             // 外部 OpenID
    String avatarId;           // 頭像 ID
    // 關聯
    Status status;
    String accountId;          // 關聯的 Account ID
    String tenantId;           // 所屬租戶 ID
    Channel channel;           // 渠道
    Boolean isJoinAile;        // 是否已加入 Aile
    Boolean isBindAile;        // 是否已綁定
    Boolean isCollectInfo;     // 是否已收集資訊
    // 類型
    ContactType type;           // RealName / Anonymous / Independent
}
```

### 7.2 客戶類型

```java
// aile-api/aile-tenant-api/.../enums/contact/ContactType.java
public enum ContactType {
    RealName,     // 實名會員（關聯了 Account）
    Anonymous,    // 匿名會員（未關聯 Account，僅有渠道 scopeId）
    Independent   // 獨立客戶（如 LineGroup 帶入的客戶，不屬於任何 Account）
}
```

### 7.3 關鍵規則

- **客戶屬於租戶，不屬於服務號**：TenantContactModel 只有 `tenantId`，沒有 `serviceNumberId`
- 同一 Account 在同一 Tenant 中只能有一條 Contact 記錄
- `type = Anonymous` 的客戶在實名登入後可被合併到 `type = RealName` 的客戶

---

## 8. ServiceMemberModel（服務號成員）

### 8.1 資料結構

MongoDB 集合：`aile.tenant.servicenumber.member`

```java
// aile-api/aile-tenant-api/.../model/servicenumber/ServiceMemberModel.java
@Document("aile.tenant.servicenumber.member")
public class ServiceMemberModel extends BaseModel {
    String serviceNumberId;            // 服務號 ID
    String memberId;                   // 成員 ID（即 TenantEmployeeModel.id）
    String accountId;                  // 關聯 Account
    String tenantId;                   // 租戶 ID
    ServiceNumberType serviceNumberType; // 服務號類型
    ServiceMemberPrivilege privilege;  // Owner / Manager / Common
    Status status;                     // Enable / Disable
}
```

### 8.2 權限層級

```java
// aile-api/aile-tenant-api/.../enums/ServiceMemberPrivilege.java
public enum ServiceMemberPrivilege {
    Owner,    // 擁有者
    Manager,  // 管理員
    Common    // 一般成員
}
```

### 8.3 關係鏈

```
Account ──→ TenantEmployee ──→ ServiceMember
                                 │
                                 ├── serviceNumberId
                                 └── privilege (Owner / Manager / Common)
```

一個員工可以同時是多個服務號的成員，每個服務號中有獨立的權限。

---

## 9. ServiceNumberScopeModel（服務號進線 Scope）

### 9.1 資料結構

MongoDB 集合：`aile.tenant.servicenumber.scope`

```java
// aile-api/aile-tenant-api/.../model/servicenumber/ServiceNumberScopeModel.java
@Document("aile.tenant.servicenumber.scope")
public class ServiceNumberScopeModel extends BaseModel {
    String tenantId;         // 租戶 ID
    String accountId;        // 帳號 ID
    String customerId;       // 客戶 ID（TenantContactModel.id）
    Channel channel;         // 渠道
    String scopeId;          // 渠道側唯一 ID（如 LINE userId 或 chat.code）
    String serviceNumberId;  // 服務號 ID
    String code;             // 渠道側主體 code
    String name;             // 渠道側顯示名稱
    String avatarId;         // 頭像 ID
    String pictureUrl;       // 頭像 URL
    String roomId;           // 對應的 Services Room ID
    Status status;           // Enable / Disable
}
```

### 9.2 核心作用

ServiceNumberScopeModel 是系統中最關鍵的橋接模型：

```
客戶 ──→ ServiceNumberScopeModel ──→ 服務號
  │            │                        │
  │     ┌──────┴──────────┐             │
  │     │ customerId      │             │
  │     │ serviceNumberId │             │
  │     │ channel         │             │
  │     │ scopeId         │             │
  │     │ roomId          │             │
  │     └─────────────────┘             │
  │                                     │
  └── TenantContactModel ───────────────┘
```

**一個客戶可以在同一服務號下有多條 Scope 記錄（不同 channel），但同一 `channel + scopeId + serviceNumberId` 組合唯一。**

---

## 10. ServiceNumberRelationModel（服務號訂閱關係）

### 10.1 資料結構

MongoDB 集合：`aile.tenant.servicenumber.relation`

```java
// aile-api/aile-tenant-api/.../model/servicenumber/ServiceNumberRelationModel.java
@Document("aile.tenant.servicenumber.relation")
public class ServiceNumberRelationModel extends BaseModel {
    String serviceNumberId;
    ServiceNumberType serviceNumberType;
    String accountId;        // 帳號 ID
    String customerId;       // 客戶 ID
    String tenantId;         // 租戶 ID
    String roomId;           // 聊天室 ID
    ServiceOpenType openType;// 公開類型
    ServiceNumberRelationStatus status; // 訂閱狀態
    String alias;            // 備註名
}
```

### 10.2 與 Scope 的區別

| 模型 | 用途 | 粒度 |
|------|------|------|
| `ServiceNumberScopeModel` | 渠道進線路由（實際收發消息） | `channel + scopeId + serviceNumberId` |
| `ServiceNumberRelationModel` | 業務層訂閱/關注關係 | `customerId + serviceNumberId` |

---

## 11. 匿名訪客與實名合併

### 11.1 匿名訪客的產生

```
1. 用戶透過 LINE 匿名進入
   → Gateway Webhook 事件
   → 若無對應 Account：建立 AccountModel（type=Anonymous）
   → 建立 TenantContactModel（type=Anonymous）
   → 建立 ServiceNumberScopeModel
   → 建立 ServiceNumberRelationModel
```

### 11.2 匿名訪客 ContactType 標記

```java
// TenantContactModel.type 可為：
ContactType.Anonymous     // 匿名訪客，未關聯實名 Account
ContactType.RealName      // 實名客戶，關聯了實名 Account
ContactType.Independent   // 獨立客戶（如 LineGroup 帶入，不經過 Account）
```

### 11.3 實名登入合併流程

當匿名訪客進行實名登入（如輸入手機號）時：

```
AnonymousVisitorMergePlanAdapter.resolve(anonymousAccountId, targetAccountId)
  │
  ├── 查詢 anonymousAccountId 下的所有 TenantContactModel（status=Enable）
  │
  ├── 逐個客戶生成 ContactMergePlan：
  │     ├── 查找目標 Account 在該租戶是否已有 Contact（targetContact）
  │     ├── 收集匿名客戶的 ServiceNumberRelation 列表
  │     ├── 收集目標客戶的 ServiceNumberRelation 列表
  │     └── 生成合併計劃（標記源客戶刪除、遷移關聯）
  │
  └── Saga 編排執行：
        ├── MergeAnonymousVisitorContactDataStep（合併客戶資料）
        ├── ProcessServiceSessionMergeStep（合併會話）
        ├── MergeLineGroupContactRelationStep（合併 LineGroup 關聯）
        └── 其他相關 Step
```

### 11.4 Saga 步驟清單

| Step | 說明 |
|------|------|
| `ResolveContactMergePlanStep` | 解析合併計劃 |
| `MergeAnonymousVisitorContactDataStep` | 合併匿名訪客客戶資料 |
| `ProcessServiceSessionMergeStep` | 合併會話記錄 |
| `MergeLineGroupContactRelationStep` | 合併 LineGroup 關聯 |
| `MarkSourceServiceSessionDeletedStep` | 標記源會話刪除 |
| `GatewayCustomerDeleteStep` | 通知 Gateway 清理舊客戶 |

---

## 12. 房間成員類型

```java
// aile-api/aile-room-api/.../enums/RoomMemberType.java
public enum RoomMemberType {
    User,           // 一般用戶（員工或客戶）
    ServiceNumber,  // 服務號
    Robot,          // 機器人
    Assistant,      // AI 助手
    Room            // 聊天室本身（系統消息）
}
```

| 成員類型 | 對應實體 | 說明 |
|----------|----------|------|
| `User` | `TenantEmployeeModel` 或 `TenantContactModel` | 房間中的人類成員 |
| `ServiceNumber` | `ServiceNumberModel` | 服務號作為房間成員 |
| `Robot` | 機器人帳號 | 自動回覆機器人 |
| `Assistant` | `TenantAssistantModel` | AI 助手 |

---

## 13. 完整關係圖

```
                          ┌──────────────────┐
                          │   AccountModel   │
                          │  (aile.account)  │
                          │  mobile, channel │
                          │  status, isSystem│
                          └───┬──────┬───────┘
                              │      │
              ┌───────────────┘      └───────────────┐
              ▼                                      ▼
   ┌──────────────────┐                  ┌──────────────────────┐
   │  AppAccountModel │                  │  AccountScopeModel   │
   │ (aile.account.   │                  │  (aile.account.      │
   │  app)            │                  │  scope)              │
   │  name, avatar    │                  │  channel, scopeId    │
   │  channel, mute   │                  └──────────────────────┘
   └──────────────────┘

              │ accountId
              │
   ┌──────────┴─────────────────────────────────────┐
   │                   Tenant (租戶)                  │
   │                                                  │
   │  ┌──────────────────────┐  ┌──────────────────┐ │
   │  │ TenantEmployeeModel  │  │TenantContactModel│ │
   │  │ (aile.tenant.        │  │(aile.tenant.     │ │
   │  │  employee)           │  │ contact)         │ │
   │  │ id → memberId        │  │ id → customerId  │ │
   │  └─────────┬────────────┘  └────────┬─────────┘ │
   │            │                        │           │
   └────────────┼────────────────────────┼───────────┘
                │                        │
         ┌──────▼──────┐          ┌──────▼───────────────┐
         │ServiceMember│          │ServiceNumberScopeModel│
         │   Model     │          │ (aile.tenant.         │
         │ memberId    │          │  servicenumber.scope) │
         │ privilege   │          │ customerId            │
         │ (Owner /    │          │ serviceNumberId       │
         │  Manager /  │          │ channel ↔ scopeId     │
         │  Common)    │          │ roomId                │
         └─────────────┘          └──────────┬────────────┘
                                             │
                                    ┌────────▼────────────┐
                                    │ServiceNumberRelation │
                                    │       Model          │
                                    │ (aile.tenant.        │
                                    │  servicenumber.      │
                                    │  relation)           │
                                    │ customerId           │
                                    │ serviceNumberId      │
                                    │ accountId            │
                                    │ status               │
                                    └──────────────────────┘
```

---

## 14. 關鍵身份流轉場景

### 14.1 新用戶首次進線

```
LINE 用戶掃碼進入服務號
  │
  ├── 無 Account → 建立 Anonymous Account
  ├── 無 TenantContact → 建立 Contact（type=Anonymous）
  ├── 建立 ServiceNumberScope（customerId + serviceNumberId + channel + scopeId）
  ├── 建立 ServiceNumberRelation（customerId + serviceNumberId + accountId）
  └── 建立 Services Room → 開始會話
```

### 14.2 匿名轉實名

```
Anonymous Account 輸入手機號進行實名登入
  │
  ├── Account 升級：type: Anonymous → RealName（填入手機號）
  ├── 觸發 Saga：AnonymousVisitorMergePlanAdapter
  │     ├── 查找該 Account 的所有 Anonymous Contact
  │     ├── 對每個 Contact 生成合併計劃
  │     └── Saga 編排執行（合併 Contact、合併 Session、合併 Relation）
  └── Contact 升級：type: Anonymous → RealName
```

### 14.3 已有 Account 進線新租戶

```
已實名 Account 透過 LINE 進入新租戶的服務號
  │
  ├── 查找 Account（依 channel + scopeId → AccountScope）
  ├── 在該租戶建立 TenantContactModel（type=RealName）
  ├── 建立 ServiceNumberScope
  └── 建立 ServiceNumberRelation
```

### 14.4 員工加入生態

```
用戶登入 → 通過邀請/擔保加入租戶
  │
  ├── 若無 Account → 建立 Account
  ├── 建立 TenantEmployeeModel（joinType=Guarantor/Invitation）
  ├── TenantBindService.send() → 發送加入生態卡片
  ├── 用戶接受 → isJoinAile=true, isBindAile=true
  └── 可被加入 ServiceMember（成為服務號客服）
```

### 14.5 LineGroup 獨立客戶

```
LINE 群組事件（MemberJoin / Messaging）
  │
  ├── 群組成員可能沒有 Account
  ├── 建立 TenantContactModel（type=Independent）
  │     └── Independent：不關聯 Account，僅作為群組內的用戶身份
  ├── 建立 LineGroupContactRelationModel
  └── 加入 LineGroup Room 為成員
```

---

## 15. 關鍵檔案索引

| 層級 | 檔案 | 說明 |
|------|------|------|
| API Model | `aile-api/aile-account-api/.../model/AccountModel.java` | 頂層帳號 |
| API Model | `aile-api/aile-account-api/.../model/AppAccountModel.java` | 應用帳號 |
| API Model | `aile-api/aile-account-api/.../model/AccountScopeModel.java` | 帳號渠道 Scope |
| API Enum | `aile-api/aile-account-api/.../enums/AccountType.java` | 帳號類型（Anonymous/NonRealName/RealName/System） |
| API Const | `aile-api/aile-account-api/.../constant/LoginType.java` | 11 種登入方式 |
| API Model | `aile-api/aile-tenant-api/.../model/TenantEmployeeModel.java` | 員工 |
| API Model | `aile-api/aile-tenant-api/.../model/TenantContactModel.java` | 客戶/聯繫人 |
| API Enum | `aile-api/aile-tenant-api/.../enums/contact/ContactType.java` | 客戶類型（RealName/Anonymous/Independent） |
| API Enum | `aile-api/aile-tenant-api/.../enums/TenantJoinType.java` | 加入方式 |
| API Model | `aile-api/aile-tenant-api/.../model/servicenumber/ServiceMemberModel.java` | 服務號成員 |
| API Enum | `aile-api/aile-tenant-api/.../enums/ServiceMemberPrivilege.java` | 服務號權限 |
| API Model | `aile-api/aile-tenant-api/.../model/servicenumber/ServiceNumberScopeModel.java` | 服務號進線 Scope |
| API Model | `aile-api/aile-tenant-api/.../model/servicenumber/ServiceNumberRelationModel.java` | 服務號訂閱 |
| API Enum | `aile-api/aile-room-api/.../enums/RoomMemberType.java` | 房間成員類型 |
| API Enum | `aile-api/aile-job-api/.../enums/UserTypeEnums.java` | 用戶類型（Employee/Contact/Visitor） |
| Service | `aile-service/aile-service-account/.../service/impl/AccountServiceImpl.java` | 帳號服務 |
| Service | `aile-service/aile-service-tenant/.../service/impl/TenantBindServiceImpl.java` | 租戶綁定服務 |
| Merge | `aile-service/aile-service-tenant/.../merge/adapter/AnonymousVisitorMergePlanAdapter.java` | 匿名訪客合併 |
| Saga | `aile-service/aile-service-tenant/.../saga/step/MergeAnonymousVisitorContactDataStep.java` | Saga 合併步驟 |
| Saga | `aile-service/aile-service-tenant/.../saga/step/ResolveContactMergePlanStep.java` | 合併計劃解析 |
