---
document_type: "design"
title: "File / Identity API 架構設計"
service: "MOMENTRY_CORE"
date: "2026-04-28"
status: "active"
current_state: "finalized"
owner: "Warren"
created_by: "OpenCode"
created_at: "2026-04-25"
version: "V1.2"
tags:
  - "api"
  - "file"
  - "identity"
  - "face"
  - "candidate"
  - "pre_chunk"
  - "reference_data"
  - "identity_embedding"
  - "clip"
related_documents:
  - "DOCS_STANDARD.md"
  - "AI_AGENT_DOCUMENTATION_GUIDE.md"
  - "_deprecated/TMDB_CHARACTER_INTEGRATION.md"
  - "_deprecated/SPEAKER_INTEGRATION.md"
  - "_deprecated/IDENTITY_SYSTEM_DESIGN.md"
  - "PROCESSORS/_CORE/RULE_SPECIFICATION.md"
  - "REFERENCE/API_ERROR_CODES.md"
  - "IDENTITY_REFERENCE_VECTOR_DESIGN.md"
ai_query_hints:
  - "查詢 File/Identity 核心架構設計"
  - "查詢 People API 端點定義"
  - "查詢 Candidate 狀態轉換流程"
  - "查詢資料庫 Schema 定義 (含 pre_chunks)"
  - "查詢 reference_data JSONB 結構"
  - "查詢 identity_embedding (CLIP ViT-L/14)"
---

# File / Identity API 架構設計文件

| 項目 | 內容 |
|------|------|
| 建立者 | OpenCode |
| 建立時間 | 2026-04-25 |
| 文件版本 | V1.1 |

---

## 版本歷史

| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.2 | 2026-04-28 | **重大更新**: 添加 face_embedding(512), voice_embedding(192), identity_embedding(768), reference_data JSONB 結構詳解, identity_type 扩展 (logo/symbol/sound/animal/environmental) | OpenCode | OpenCode |
| V1.1 | 2026-04-25 | **重大更新**: 移除 faces 表 (方案 A), 新增 pre_chunks 表, 統一命名為 file_uuid, 更新 Response 格式 | OpenCode | OpenCode |
| V1.0 | 2026-04-25 | 創建 File/Identity API 架構設計 | OpenCode | OpenCode |

---

## 概述

本文檔定義 Momentry Core 全新架構下的 File、Identity、Candidate 核心概念與 API 設計。
核心理念：**僅有兩種核心實體 — File（任何檔案）與 Identity（任何可識別列管的物件）**。

---

## 核心設計理念

### 實體定義

| 實體 | 說明 | 範例 |
|------|------|------|
| **File** | 任何檔案 | video (現階段僅處理 video), pdf, ppt... |
| **Identity** | 任何可識別列管的物件 | 人、品牌、物件、概念... |
| **Pre-chunk** | 處理器產出的原始數據單元 | 幀 (Frame)、語音段落 (Segment) |
| **Candidate** | 邏輯狀態：`identity_id IS NULL` 的 Face Pre-chunk | 待確認的人臉 |

### 關係模型

```
File ──[包含]──→ Pre-chunk (Frame/Segment)
Pre-chunk ──[歸屬於]──→ Identity (用信心度標示關係, 若為 NULL 則為 Candidate)
Identity ──[出現在]──→ File (通過 Pre-chunk 或 file_identities 關聯)
```

### 生命週期

**File 生命週期**:
```
上傳 → 自動註冊 → 取得 file_uuid → 觸發 probe → File 分類 → 等待 Rule 排程處理
```

**Identity 生命週期 (People)**:
```
檢測到 Face → 存入 Pre-chunk (Candidate)
    ↓ Agent 分析建議 / 人工確認
關聯 Identity (不再為 Candidate)
```

**Candidate 狀態轉換**:
* **定義**: Candidate 不是獨立表格，而是 `pre_chunks` 中 `identity_id IS NULL` 的 Face 數據。
* **確認**: 更新 `identity_id` → 成為已確認身份。
* **剔除**: 將 `identity_id` 設回 `NULL` → 重新成為 Candidate。

---

## 資料庫 Schema (全新，不與舊系統共用)

### Files 表

| 欄位 | 類型 | 必填 | 說明 |
|------|------|------|------|
| file_uuid | UUID | Yes | 唯一識別 (自動產生) |
| file_type | VARCHAR(20) | Yes | video, pdf, ppt, png... |
| file_path | TEXT | Yes | 檔案路徑 |
| file_name | TEXT | Yes | 檔名 |
| file_size | BIGINT | No | 檔案大小 (bytes) |
| mime_type | VARCHAR(100) | No | MIME 類型 |
| probe_metadata | JSONB | No | probe 處理器輸出元數據 |
| processing_status | VARCHAR(20) | No | pending, processing, completed |
| created_at | TIMESTAMPTZ | Yes | 建立時間 |
| updated_at | TIMESTAMPTZ | Yes | 更新時間 |

```sql
CREATE TABLE files (
    file_uuid           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    file_type           VARCHAR(20) NOT NULL,
    file_path           TEXT NOT NULL,
    file_name           TEXT NOT NULL,
    file_size           BIGINT,
    mime_type           VARCHAR(100),
    probe_metadata      JSONB DEFAULT '{}',
    processing_status   VARCHAR(20) DEFAULT 'pending',
    created_at          TIMESTAMPTZ DEFAULT NOW(),
    updated_at          TIMESTAMPTZ DEFAULT NOW()
);
```

### Pre-chunks 表 (處理器原始數據)

**說明**: 所有 Processor (YOLO, Face, ASR...) 產出的數據皆存於此表。
* **Video File**: 最小單位為 **Frame (幀)** (`coordinate_type = 'frame'`)。
* **Text File**: 最小單位為 Word/Sentence (`coordinate_type = 'text'`)。

| 欄位 | 類型 | 必填 | 說明 |
|------|------|------|------|
| id | BIGSERIAL | Yes | 主鍵 |
| file_uuid | UUID | Yes | 所屬 File |
| processor_type | VARCHAR(20) | Yes | 產生此數據的處理器 (yolo, face, asr...) |
| coordinate_type | VARCHAR(20) | Yes | 座標類型 (frame, text, page...) |
| coordinate_index | BIGINT | Yes | 索引值 (幀號、段落號) |
| timestamp | FLOAT | No | 時間位置 (秒) |
| data | JSONB | Yes | 處理器原始輸出 (例如: { "objects": [...] }) |
| identity_id | UUID | No | **若為 Face 且歸屬 Identity 則填寫，否則為 NULL (Candidate)** |
| confidence | FLOAT | No | 匹配信心度 |
| created_at | TIMESTAMPTZ | Yes | 建立時間 |

```sql
CREATE TABLE pre_chunks (
    id                  BIGSERIAL PRIMARY KEY,
    file_uuid           UUID REFERENCES files(file_uuid) ON DELETE CASCADE,
    processor_type      VARCHAR(20) NOT NULL, -- 'yolo', 'face', 'ocr', 'asr'...
    coordinate_type     VARCHAR(20) DEFAULT 'frame', -- 'frame' for video
    coordinate_index    BIGINT NOT NULL, -- Frame number
    timestamp           FLOAT,
    data                JSONB NOT NULL, -- Raw processor output
    identity_id         UUID REFERENCES identities(identity_id), -- Link to Identity (NULL = Candidate)
    confidence          FLOAT,
    created_at          TIMESTAMPTZ DEFAULT NOW()
);

-- 索引優化
CREATE INDEX idx_pre_chunks_file ON pre_chunks(file_uuid);
CREATE INDEX idx_pre_chunks_type ON pre_chunks(processor_type);
CREATE INDEX idx_pre_chunks_identity ON pre_chunks(identity_id) WHERE identity_id IS NOT NULL;
```

### Identities 表

| 欄位 | 類型 | 必填 | 說明 |
|------|------|------|------|
| identity_id | UUID | Yes | 唯一識別 (自動產生) |
| name | TEXT | Yes | 顯示名稱 |
| identity_type | VARCHAR(30) | Yes | people, brand, object, concept, logo, symbol, sound, animal, environmental... |
| source | VARCHAR(20) | No | manual, tmdb, agent_suggested, ai_detection |
| status | VARCHAR(20) | No | pending, confirmed, skipped |
| face_embedding | VECTOR(512) | No | 參考臉向量 (ArcFace) - 用於人臉比對 |
| voice_embedding | VECTOR(192) | No | 參考聲紋向量 (ECAPA-TDNN) - 用於聲音比對 |
| identity_embedding | VECTOR(768) | No | 身份向量 (CLIP ViT-L/14) - 用於 logo/symbol/object 搜索 |
| reference_data | JSONB | No | 1對多參考向量存儲 (多角度/多場景/多版本 embedding) |
| metadata | JSONB | No | 擴展屬性 |
| created_at | TIMESTAMPTZ | Yes | 建立時間 |
| updated_at | TIMESTAMPTZ | Yes | 更新時間 |

```sql
CREATE TABLE identities (
    identity_id         UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name                TEXT NOT NULL,
    identity_type       VARCHAR(30) NOT NULL,
    source              VARCHAR(20) DEFAULT 'manual',
    status              VARCHAR(20) DEFAULT 'pending',
    
    -- 參考向量 (用於自動比對)
    face_embedding      VECTOR(512),             -- 參考臉向量 (ArcFace)
    voice_embedding     VECTOR(192),             -- 參考聲紋向量 (ECAPA-TDNN)
    identity_embedding  VECTOR(768),             -- 身份向量 (CLIP ViT-L/14)
    
    -- 1對多參考向量存儲
    reference_data      JSONB DEFAULT '{}',      -- 多角度/多場景/多版本 embedding
    metadata            JSONB DEFAULT '{}',
    created_at          TIMESTAMPTZ DEFAULT NOW(),
    updated_at          TIMESTAMPTZ DEFAULT NOW()
);
```

#### reference_data JSONB 結構詳解

`reference_data` 用於存儲同一 Identity 的多個參考向量，支援 1對多匹配，提高識別鲁棒性。

**完整結構範例**:
```json
{
  "face_embeddings": [
    {
      "embedding": [0.1, 0.2, ...],
      "source": "tmdb_images",
      "image_url": "https://image.tmdb.org/t/p/original/xxx.jpg",
      "angle": "frontal",
      "quality_score": 0.95,
      "created_at": "2026-04-28T10:00:00Z"
    },
    {
      "embedding": [0.3, 0.4, ...],
      "source": "tmdb_images",
      "image_url": "https://image.tmdb.org/t/p/original/yyy.jpg",
      "angle": "profile_left",
      "quality_score": 0.88,
      "created_at": "2026-04-28T10:05:00Z"
    }
  ],
  "voice_embeddings": [
    {
      "embedding": [0.1, 0.2, ...],
      "source": "video_segment",
      "file_uuid": "vid_001",
      "timestamp_start": 120.5,
      "timestamp_end": 135.2,
      "quality_score": 0.88,
      "created_at": "2026-04-28T11:00:00Z"
    }
  ],
  "identity_embeddings": [
    {
      "embedding": [0.1, 0.2, ...],
      "source": "logo_image",
      "image_url": "https://www.accusys.com.tw/wp-content/uploads/2023/03/Accusys-Orange-2017.png",
      "context": "brand_logo",
      "created_at": "2026-04-28T12:00:00Z"
    }
  ],
  "sound_embeddings": [
    {
      "embedding": [0.1, 0.2, ...],
      "source": "audio_segment",
      "file_uuid": "vid_001",
      "timestamp_start": 10.0,
      "timestamp_end": 15.0,
      "sound_type": "animal_dog_bark",
      "created_at": "2026-04-28T13:00:00Z"
    }
  ],
  "image_urls": [
    "https://image.tmdb.org/t/p/original/xxx.jpg",
    "https://www.accusys.com.tw/wp-content/uploads/2023/03/Accusys-Orange-2017.png"
  ]
}
```

**欄位說明**:

| 欄位 | 類型 | 說明 |
|------|------|------|
| face_embeddings | Array | 多個 512-dim ArcFace embedding (不同角度/定妝造型) |
| voice_embeddings | Array | 多個 192-dim ECAPA-TDNN embedding (不同音質片段) |
| identity_embeddings | Array | 多個 768-dim CLIP ViT-L/14 embedding (logo/symbol/object) |
| sound_embeddings | Array | TBD - 動物叫聲、雷雨、槍炮、樂器 (Phase 5+) |
| image_urls | Array | 參考圖片 URL 列表 |

**子欄位說明**:

| 欄位 | 類型 | 說明 |
|------|------|------|
| embedding | Array | 向量值 |
| source | String | 來源: tmdb_profile, tmdb_images, manual_upload, auto_detection, logo_image, audio_segment |
| image_url | String | 圖片 URL (face/identity) |
| file_uuid | UUID | 檔案 UUID (voice/sound) |
| timestamp_start/end | Float | 時間範圍 (voice/sound) |
| angle | String | 人臉角度: frontal, profile_left, profile_right, three_quarter |
| quality_score | Float | 質量評分 (0.0-1.0) |
| context | String | 識別場景: brand_logo, symbol, object, concept |
| sound_type | String | 聲音類型: animal_dog_bark, environmental_thunder, weapon_gunshot, musical_guitar |
| created_at | String | 建立時間 |

**設計理念**:
1. **1對多匹配**: 同一 Identity 可有多個參考向量，提高識別鲁棒性
2. **多角度覆蓋**: 人臉正面、側面、三側角度，覆蓋不同拍攝角度
3. **多場景覆蓋**: Logo/Symbol 在不同場景（白底、黑底、複雜背景）的 embedding
4. **質量評分**: 記錄每個參考向量的質量，用於加權匹配
5. **來源追溯**: 記錄每個 embedding 的來源，方便追溯和更新

### File-Identities 表 (關聯表 - 用於記錄聚合後的結果或特定角色資訊)

**說明**: 用於記錄 Identity 在 File 中的**整體出現資訊** (如：角色名、定妝造型描述)。
具體的臉部幀數據仍儲存在 `pre_chunks` 表中。

| 欄位 | 類型 | 必填 | 說明 |
|------|------|------|------|
| id | BIGSERIAL | Yes | 主鍵 |
| file_uuid | UUID | Yes | File UUID |
| identity_id | UUID | Yes | Identity UUID |
| role_name | TEXT | No | 劇中角色名 (e.g., 蘇麗珍) |
| costume_design | TEXT | No | 定妝造型描述 (e.g., 老妝) |
| presentation | TEXT[] | No | 出現形式 (face, speaker, pose, name_mention) |
| timestamp_start | FLOAT | No | 最早出現時間 |
| timestamp_end | FLOAT | No | 最晚出現時間 |
| match_confidence | FLOAT | No | 整體匹配置信度 |
| is_confirmed | BOOLEAN | No | 是否已人工確認 |
| status | VARCHAR(20) | No | detected, matched, confirmed |
| created_at | TIMESTAMPTZ | Yes | 建立時間 |

```sql
CREATE TABLE file_identities (
    id                  BIGSERIAL PRIMARY KEY,
    file_uuid           UUID REFERENCES files(file_uuid) ON DELETE CASCADE,
    identity_id         UUID REFERENCES identities(identity_id) ON DELETE CASCADE,
    role_name           TEXT,
    costume_design      TEXT,
    presentation        TEXT[] DEFAULT '{}',
    timestamp_start     FLOAT,
    timestamp_end       FLOAT,
    match_confidence    FLOAT,
    is_confirmed        BOOLEAN DEFAULT FALSE,
    status              VARCHAR(20) DEFAULT 'detected',
    created_at          TIMESTAMPTZ DEFAULT NOW(),
    UNIQUE(file_uuid, identity_id)
);
```

### Categories 表

| 欄位 | 類型 | 必填 | 說明 |
|------|------|------|------|
| code | VARCHAR(20) | Yes | 階層編號 (P-001-010/010) |
| name | TEXT | Yes | 分類名稱 |
| parent_code | VARCHAR(20) | No | 父分類代碼 |
| category_type | VARCHAR(20) | No | file, identity, both |
| description | TEXT | No | 描述 |
| created_at | TIMESTAMPTZ | Yes | 建立時間 |

```sql
CREATE TABLE categories (
    code                VARCHAR(20) PRIMARY KEY,
    name                TEXT NOT NULL,
    parent_code         VARCHAR(20) REFERENCES categories(code),
    category_type       VARCHAR(20) DEFAULT 'both',
    description         TEXT,
    created_at          TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE file_categories (
    file_uuid           UUID REFERENCES files(file_uuid),
    category_code       VARCHAR(20) REFERENCES categories(code),
    PRIMARY KEY (file_uuid, category_code)
);

CREATE TABLE identity_categories (
    identity_id         UUID REFERENCES identities(identity_id),
    category_code       VARCHAR(20) REFERENCES categories(code),
    PRIMARY KEY (identity_id, category_code)
);
```

---

## API 端點設計

### API Response 格式規範

**成功 Response (List)**:
```json
{
  "success": true,
  "total": 156,
  "page": 1,
  "page_size": 20,
  "data": [...]
}
```

**成功 Response (單一資源)**:
```json
{
  "success": true,
  "data": {...}
}
```

**成功 Response (操作)**:
```json
{
  "success": true,
  "message": "操作成功"
}
```

**錯誤 Response**:
```json
{
  "success": false,
  "error": {
    "code": "E001_NOT_FOUND",
    "message": "找不到指定的資源"
  }
}
```

### Candidates API

**定義**: 查詢 `pre_chunks` 表中 `processor_type = 'face'` 且 `identity_id IS NULL` 的紀錄。

| Method | Endpoint | 功能 | 說明 |
|--------|----------|------|------|
| `GET` | `/people/candidates` | 列出未確認的 face | 無 uuid 參數 = 全域搜尋 |

**Query 參數**:
```
?file_uuid={uuid}      # 指定 File (可選)
&page=1
&page_size=20
&sort=created_at       # 排序欄位
```

**Request**:
```bash
curl -X GET "https://api.yourdomain.com/people/candidates" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Response**:
```json
{
  "success": true,
  "total": 50,
  "page": 1,
  "page_size": 20,
  "data": [
    {
      "pre_chunk_id": 1001,
      "file_uuid": "vid_001",
      "frame_index": 3600,
      "timestamp": 120.5,
      "preview_image_url": "https://cdn.xxx.com/faces/face_11.jpg",
      "data": { "bounding_box": {...} },
      "agent_suggestion": {
        "type": "match_existing",
        "identity_id": "abc123",
        "identity_name": "張曼玉",
        "confidence": 0.85
      }
    }
  ]
}
```

### People/Identities API

| Method | Endpoint | 功能 | 說明 |
|--------|----------|------|------|
| `GET` | `/people` | List All | 列出所有 People Identity |
| `POST` | `/people/search` | Search | 複雜搜尋條件 |
| `GET` | `/people/{identity_id}` | Detail | 獲取單個 Identity 詳情 |
| `GET` | `/people/{identity_id}/resolve` | 出現在哪些 File | 獲取此人在哪些 File 中出現 |
| `POST` | `/people` | Create | 建立新的 People Identity |
| `PATCH` | `/people/{identity_id}` | Update | 更新 Identity 資訊 |
| `POST` | `/people/merge` | Merge | 合併多個 Identity |
| `POST` | `/people/{identity_id}/confirm-candidate` | Confirm | 確認 Candidate (更新 pre_chunk identity_id) |
| `POST` | `/people/{identity_id}/remove-candidate` | Remove | 移除關聯 (設回 NULL) |

#### List All

**Request**:
```bash
curl -X GET "https://api.yourdomain.com/people?page=1&page_size=20&status=confirmed" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Response**:
```json
{
  "success": true,
  "total": 156,
  "page": 1,
  "page_size": 20,
  "data": [
    {
      "identity_id": "abc123",
      "name": "張曼玉",
      "identity_type": "people",
      "preview_image_url": "https://cdn.xxx.com/identities/abc123.jpg",
      "tmdb_id": 1234,
      "source": "tmdb",
      "status": "confirmed",
      "total_files": 5
    }
  ]
}
```

#### Confirm Candidate (更新 Face 歸屬)

**指定給現有 Identity**:
```bash
curl -X POST "https://api.yourdomain.com/people/{identity_id}/confirm-candidate" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "file_uuid": "vid_001",
    "pre_chunk_id": 1001
  }'
```

*後端邏輯*:
```sql
UPDATE pre_chunks 
SET identity_id = '...', confidence = 0.95 
WHERE id = 1001 AND file_uuid = 'vid_001';
```

**Response**:
```json
{
  "success": true,
  "message": "Candidate confirmed"
}
```

#### Remove Candidate (取消歸屬)

```bash
curl -X POST "https://api.yourdomain.com/people/{identity_id}/remove-candidate" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "file_uuid": "vid_001",
    "pre_chunk_id": 1001
  }'
```

*後端邏輯*:
```sql
UPDATE pre_chunks 
SET identity_id = NULL, confidence = NULL 
WHERE id = 1001;
```

---

## 錯誤碼定義

詳細錯誤碼請參考: `REFERENCE/API_ERROR_CODES.md`

| 錯誤碼 | HTTP 狀態 | 說明 |
|--------|-----------|------|
| `E001_NOT_FOUND` | 404 | 找不到資源 (File, Identity, Pre-chunk) |
| `E002_DUPLICATE` | 409 | 資源已存在 (如重複註冊 Identity) |
| `E003_VALIDATION` | 400 | 參數驗證失敗 |
| `E004_PROCESSOR` | 500 | 處理器執行失敗 |
| `E005_INTERNAL` | 500 | 系統內部錯誤 |

---

## 實作計畫

### Phase 0: 系統備份 (立即執行)

* [ ] 備份現有 PostgreSQL 資料庫
* [ ] 備份現有程式碼
* [ ] 記錄現有版本

### Phase 1: 建立新資料庫 Schema

* [ ] 建立 `files`, `identities`, `pre_chunks` 表
* [ ] 建立 `file_identities`, `categories` 表
* [ ] 建立索引
* [ ] 建立測試資料

### Phase 2: 核心 API 實作

* [ ] Candidates API (`GET /people/candidates`) - 查詢 `identity_id IS NULL`
* [ ] Identity CRUD API (`GET/POST/PATCH /people`)
* [ ] Identity Search API (`POST /people/search`)
* [ ] Identity Resolve API (`GET /people/{id}/resolve`)
* [ ] Candidate Management (`POST /people/{id}/confirm-candidate`, `remove-candidate`)
* [ ] Status API (`GET /people/status`)

### Phase 3: Processor 整合 (Pre-chunk 寫入)

* [ ] 修改 YOLO, Face, OCR 處理器，改寫入 `pre_chunks` 表
* [ ] 實作 `PROCESSOR_RESUME_STRATEGY.md` 中的 Checkpoint 邏輯
* [ ] probe Processor 整合 (ffprobe → File 分類)

### Phase 4: Portal 前端

* [ ] Candidates 介面
* [ ] Identity 管理介面
* [ ] File 管理介面

### Phase 5: 非 People Identity (待辦事項)

* [ ] Brand Identity 支援
* [ ] Object Identity 支援
* [ ] Concept Identity 支援

---

## 待辦事項

| 項目 | 優先級 | 說明 |
|------|--------|------|
| 系統備份 | 高 | 立即執行 |
| 新資料庫 Schema | 高 | Phase 1 |
| Core API | 高 | Phase 2 |
| Processor 整合 | 中 | Phase 3 (寫入 pre_chunks) |
| Portal 前端 | 中 | Phase 4 |
| 非 People Identity | 低 | Phase 5 (待辦事項) |

---

## 限制條件

* 本設計為全新架構，不與現有系統共用資料
* 需要做新的處理器版本產生新的輸出 (寫入 `pre_chunks` 而非 `chunks`)
* 非 People Identity 列入待辦事項，不在本次實作範圍
* Face 的唯一識別為 `file_uuid` + `coordinate_index` (Frame Number)

---

## 相關文件

* `docs_v1.0/STANDARDS/DOCS_STANDARD.md` - 文件創建規範
* `docs_v1.0/ARCHITECTURE/` - 架構相關文件
* `docs_v1.0/PROCESSORS/_CORE/PROCESSOR_RESUME_STRATEGY.md` - 處理器續傳機制
* `docs_v1.0/PROCESSORS/_CORE/RULE_SPECIFICATION.md` - Rule 依賴與數據流定義

---

## 版本資訊

* 版本: V1.2
* 建立日期: 2026-04-25
* 文件更新: 2026-04-28
