- Fix markdown lint issues (MD030, MD047, MD051, MD028, MD005) - Update AI agents, architecture, implementation docs - Add new identity, face recognition, and API documentation - Remove deprecated face/person API guides
7.1 KiB
7.1 KiB
file_uuid 設計理念與規格
Version: 1.0 | Date: 2026-04-30 Architecture: Birth Identity Model (戶籍制度模型)
1. 核心概念
系統將每個媒體檔案視為一個「自然人」,擁有一個終身不變的身份證字號 (file_uuid)。
| 戶籍概念 | 系統對應 | 說明 |
|---|---|---|
| 身分證字號 | file_uuid |
檔案的終身唯一標識,出生後永不變更 |
| 出生登記 | 首次 register |
檔案首次被系統納管,觸發分析處理 (ASR, Face, etc.) |
| 戶籍地 | file_path |
檔案當前存放位置,可隨搬家而變更 |
| 主管單位 | MAC Address |
核發身份的伺服器/機器,確保跨機器的管轄獨立 |
| 居住證申請時間 | registration_time |
檔案在該管轄單位登記的時間戳記 |
2. file_uuid 生成公式
file_uuid = SHA256( MAC_Address | Birthday | Canonical_Path | Filename )[0:32]
設計原則
| 原則 | 說明 |
|---|---|
| 唯一性 | 同一台機器上,相同路徑與檔名只會產生一個 UUID |
| 穩定性 | 生日 (Birthday) 是身份錨點。如果檔案在原地重新註冊,系統會找回原始生日,確保 UUID 不變 |
| 管轄獨立 | 不同機器的 MAC 不同,確保跨伺服器身份獨立 |
| 路徑綁定 | Canonical Path 參與計算。檔案移動到新路徑會產生新 UUID(視為新環境下的註冊) |
| 隱私保護 | 所有元素經 Hash 處理,無法反推出原始資訊 |
關鍵元素
| 元素 | 說明 |
|---|---|
Birthday |
首次註冊的時間戳記。系統會透過檔名查詢資料庫,找回原始生日,確保身份連續 |
Canonical Path |
檔案的絕對路徑。確保位置的唯一性 |
Filename |
檔案名稱 |
3. 生命週期
3.1 出生 (Birth / 首次納管)
當檔案首次被系統發現並執行 register 時:
1. 取得本机 MAC Address
2. 讀取 Filename
3. 查詢資料庫:是否有同檔名 (Filename) 的紀錄?
├─ 有紀錄 → 取出其 registration_time 作為「生日 (Birthday)」
└─ 無紀錄 → 使用 NOW() 作為「生日 (Birthday)」
4. 計算 file_uuid = SHA256(MAC | Birthday | Canonical_Path | Filename)[0:32]
5. 檢查 DB 是否已存在該 UUID
├─ 已存在 → 拒絕重複登記 (已有出生紀錄)
└─ 不存在 → 建立新生紀錄
6. 記錄 registration_time (居住證申請時間)
出生後:file_uuid 即成為該檔案的終身身份,不可更改。
3.2 搬家 (Move / 路徑變更)
當檔案從 /data/demo/ 移動到 /archive/2024/ 時:
1. 檔案路徑變更 (Canonical Path 改變)
2. 系統以新 Path 計算 UUID → 產生新 UUID
3. 查詢 DB → 找不到該 UUID (視為新身份)
4. 但若檔名相同,會查詢到舊的「生日 (Birthday)」
5. 執行動作:
├─ 建立新紀錄 (新 UUID,新路徑)
├─ 使用原始的 Birthday (保持血緣關係)
└─ 可選擇是否繼承舊紀錄的分析結果
關鍵邏輯:
- 路徑改變 = 新環境 = 新 UUID
- 但透過 Birthday 查詢機制,系統知道這是同一個「人」搬到了新家
3.3 跨機器遷移 (Cross-Machine)
當檔案從 Server-A 複製到 Server-B 時:
Server-A (MAC: aa:bb:cc:dd:ee:ff):
file_uuid = SHA256("aa:bb:cc:dd:ee:ff|Birthday|/path|video.mp4") → "abc123..."
Server-B (MAC: 11:22:33:44:55:66):
file_uuid = SHA256("11:22:33:44:55:66|Birthday|/path|video.mp4") → "def456..."
- 結果:兩台伺服器各自擁有獨立管轄權
- 意義:各管各的戶口,互不干擾
4. 資料庫欄位定義
videos 表
| 欄位 | 類型 | 說明 | 範例 |
|---|---|---|---|
file_uuid |
VARCHAR(32) | 身分證字號 (不可變) | 384b0ff44aaaa1f1... |
file_path |
TEXT | 戶籍地址 (可變) | /data/demo/video.mp4 |
file_name |
VARCHAR(255) | 原始檔名 | video.mp4 |
registration_time |
TIMESTAMPTZ | 居住證申請時間 | 2026-04-30T02:00:00+08 |
birth_registration |
JSONB | 出生登記詳情 | 見下方結構 |
birth_registration JSONB 結構
{
"registration_source": {
"mac_address": "ba:f5:ee:bc:45:78",
"original_path": "/Users/accusys/momentry/var/sftpgo/data/demo",
"original_filename": "Old_Time_Movie_Show_-_Charade_1963.HD.mov",
"timestamp": "2026-04-29T02:25:14+08:00"
}
}
5. 代碼實作
5.1 UUID 計算 (src/core/storage/uuid.rs)
pub fn compute_birth_uuid(
mac_address: &str,
birthday: &str,
path: &str,
filename: &str,
) -> String {
let key = format!("{}|{}|{}|{}", mac_address, birthday, path, filename);
let hash = Sha256::digest(key.as_bytes());
hex::encode(hash)[0..32].to_string()
}
5.2 註冊流程 (src/api/server.rs)
// 1. 取得 MAC、路徑與檔名
let mac_address = get_mac_address();
let canonical_path = path.canonicalize()...;
let filename = path.file_name()...;
// 2. 查詢生日 (Identity Anchor)
// 以檔名查詢 DB,若有紀錄則使用原始生日,否則使用 NOW()
let birthday = db.find_birthday_by_filename(&filename).await.unwrap_or(now());
// 3. 計算穩定身份
let file_uuid = compute_birth_uuid(&mac_address, &birthday, &canonical_path, &filename);
// 4. 檢查是否已出生
if let Some(existing) = db.get_video_by_uuid(&file_uuid).await? {
if existing.registration_time.is_some() {
return Ok(already_exists_response);
}
}
// 5. 新生登記 + 觸發分析
db.register_video(&record).await?;
6. 情境對照表
| 情境 | file_uuid | file_path | Birthday | 觸發分析? | 說明 |
|---|---|---|---|---|---|
| 首次註冊 | 新生成 | 記錄當前路徑 | NOW() | ✅ 是 | 出生登記,全面納管 |
| 同一檔案再次註冊 | 相同 | 不變 | 原始 | ❌ 否 | 已有戶籍,拒絕重複 |
| 檔案移動到同機另一目錄 | 不同 | 新路徑 | 原始 | ✅ 是 | 新位置視為新環境 |
| 檔案複製到另一台伺服器 | 不同 | 記錄新路徑 | ✅ 是 | 新管轄區,獨立登記 | |
| 檔名變更 | 不同 | 記錄新路徑 | ✅ 是 | 視為不同身份 | |
| 檔案刪除後重新加入 | 相同 | 記錄新路徑 | ⚠️ 視情況 | 若 DB 紀錄仍存在,可恢復關聯 |
7. 設計優勢
- 身份錨點:透過 Birthday 機制,即使路徑改變,系統仍能識別檔案的歷史血緣
- 路徑綁定:UUID 包含 Canonical Path,確保每個位置的檔案都有獨立身份,避免混淆
- 管轄清晰:MAC Address 確保每台伺服器的數據獨立
- 可追溯性:
birth_registration記錄原始出處與 Birthday,便於審計 - 防止重複:系統以 UUID 為準,同一位置同一檔案絕不會重複登記
8. 相關文件
| 文件 | 說明 |
|---|---|
src/core/storage/uuid.rs |
UUID 生成實作 |
src/api/server.rs |
註冊端點與流程 |
src/core/ingestion.rs |
Watcher 自動 ingestion 邏輯 |
docs_v1.0/UUID_LENGTH_ISSUE.md |
舊版 UUID 長度問題分析 |
docs_v1.0/UUID_CLEANUP_PLAN.md |
歷史數據清理方案 |