第 6 章:控制權交接協議
本章定義 Handover_Policy(控制權交接策略)的協議流程,包括三類策略的語意、交接的原子性保證、逾時回滾和通知機制。本章對應藍圖 §2.4 的設計意圖。
6.1 適用場景
控制權交接發生在多個控制方需要先後使用同一 Terminal_Resource 的場景中。本規範定義兩類核心交接:
- Fay-to-Fay:一個 Fay 將其持有的 Session 控制權轉移給另一個 Fay
- Fay-to-Human:Fay 將控制權歸還給人類使用者,或人類使用者將控制權委託給 Fay
本規範以 Fay-to-Fay 為主要描述對象。Fay-to-Human 交接複用相同流程,將「人類使用者」建模為透過特殊介面直接與終端 OS 互動的實體。
6.2 交接發起
6.2.1 觸發條件
交接由以下場景之一觸發:
- 新 Fay 主動請求資源:Fay-B 透過 AuthRequest 請求存取已被 Fay-A 佔用的資源
- 現 Fay 主動讓出:Fay-A 透過
SessionTransferRequest主動請求將控制權交給指定 Fay-B - 管理觸發:人類使用者或管理介面要求轉移控制權
6.2.2 交接請求訊息
SessionTransferRequest (body of ProtocolMessage) {
required source_session_id : Session_ID // 目前持有控制權的 Session
required target_fay_id : Fay_ID // 目標接管方
required target_credential : CredentialContent // 目標方的授權憑證
required handover_reason : string
optional handover_metadata : map<string, string>
}
終端收到交接請求後啟動交接評估流程。
6.3 交接評估
終端按以下步驟評估交接是否允許:
6.3.1 第 1 步:源 Session 校驗
- 驗證
source_session_id對應的 Session 存在且處於active - 驗證發起方有權請求此次交接(如來自該 Session 的 iFay_Runtime 或具備管理權限的實體)
失敗 → 返回 E_HANDOVER_INVALID_SOURCE
6.3.2 第 2 步:目標授權校驗
- 校驗
target_credential是否合法(按第 3/4 章規則完整校驗) - 校驗
target_fay_id對該資源在原 Session 的access_mode下有授權
失敗 → 返回 E_HANDOVER_INVALID_TARGET
6.3.3 第 3 步:策略評估
終端按 §6.4 套用 Handover_Policy 決定是否允許交接。
失敗 → 返回 E_HANDOVER_REJECTED_BY_POLICY
6.3.4 第 4 步:原子性預佔
終端在策略評估通過後立即將原 Session 切換到 handover_pending,進入預佔狀態:
- 該資源在交接完成前不接受其他控制權請求
- 原 Session 仍能維持心跳(保持 active 等價的心跳要求)但不能發起新的資源操作
6.4 交接策略類型
Handover_Policy 按 Resource_ID 粒度配置,每個資源 MAY 採用不同策略。本規範定義三種策略類型,所有終端 MUST 至少實作 §6.4.1 優先級規則指令稿。
6.4.1 優先級規則指令稿(Priority Rule Script)
終端按預定義規則指令稿計算源 Session 與目標 Fay 的優先級分數,分數高者獲得控制權。
配置結構:
PriorityPolicyConfig {
required policy_type : "priority_script"
required script_id : string // 終端預配置的指令稿識別
optional parameters : map<string, string>
}
評估流程:
- 終端載入
script_id對應的規則指令稿 - 輸入:源 Session 資訊、目標 Fay 識別、目標憑證 grants、目前時間、Resource_ID 元資料
- 輸出:源優先級分數
S_source、目標優先級分數S_target - 決策:
S_target > S_source→ 允許交接;否則拒絕
規則指令稿的具體語言(如 CEL、Lua 子集、JSON Logic)由實作選擇,但 MUST:
- 是確定性的(相同輸入產生相同輸出)
- 不能存取網路或檔案系統
- 執行時間限制在 100 ms 內
6.4.2 AI 模型即時判定(AI Model Real-time Decision)
終端呼叫預整合的 AI 模型對目前情境進行即時判定。
配置結構:
AIPolicyConfig {
required policy_type : "ai_model"
required model_endpoint : string // 終端可存取的模型推論端點
optional context_fields : array<string>
required decision_timeout_ms : uint32 (default 500)
}
評估流程:
- 終端建構決策請求,包含 source/target 資訊和
context_fields指定的情境 - 呼叫 AI 模型推論端點
- 模型返回決策:
allow/reject/require_human require_human時降級到 §6.4.3 人類使用者決策
終端 MUST:
- 設定強制逾時(預設 500 ms),逾時按
reject處理 - 快取最近決策結果以避免高頻抖動(快取有效期 ≤ 5 秒)
- AI 模型不可用時降級到優先級規則指令稿
6.4.3 人類使用者決策(Human User Decision)
終端透過使用者介面請求人類使用者做出決策。
配置結構:
HumanPolicyConfig {
required policy_type : "human_decision"
required ui_channel : enum["system_dialog", "companion_app", "external_panel"]
required decision_timeout_seconds : uint32 (default 30)
required default_action : enum["allow", "reject"] // 逾時預設動作
}
評估流程:
- 終端透過
ui_channel向人類使用者呈現交接請求詳情 - 等待使用者輸入:允許 / 拒絕
- 逾時 → 按
default_action處理
人類決策模式 MUST:
- 在 UI 中清晰展示:源 Fay 識別、目標 Fay 識別、資源識別、存取模式、交接原因
- 不在 UI 中展示敏感憑證細節(如簽章、金鑰 ID)
- 預設動作建議設為
reject(保守安全)
6.5 原子性保證
交接 MUST 滿足原子性:在任意時刻,一個 Resource_ID 最多有一個活躍控制方。
6.5.1 原子序列
終端 MUST 按以下順序執行交接,每一步在臨界區內完成:
[T0] handover_pending 進入:源 Session 狀態切換,資源進入預佔
[T1] 終止源 Session:source_session_id 狀態 active → terminating
觸發 OS 存取控制撤銷
[T2] 資源回收完成:source 狀態 terminating → terminated
此時資源處於「無活躍 Session」狀態
[T3] 建立目標 Session:按 §5.2 流程為目標 Fay 建立新 Session
狀態進入 creating
[T4] OS 存取控制下發:為目標 Fay 啟用資源存取
[T5] 目標 Session 切換 active:交接完成
外部觀察者在 [T2] 與 [T3] 之間觀察到的資源狀態是「無活躍 Session」,不會觀察到兩個 Session 同時活躍。
6.5.2 中間步驟失敗的回滾
若 [T0]–[T2] 中任何步驟失敗:
- 源 Session MUST 回滾到
active - 資源回收預佔撤銷
- 返回
E_HANDOVER_FAILED_AT_RELEASE
若 [T3]–[T4] 失敗(源已終止但目標無法建立):
- 終端 MUST 立即清理資源(資源進入「無活躍 Session」狀態)
- 通知原 iFay_Runtime(源 Session 已終止)和目標 iFay_Runtime(接管失敗)
- 返回
E_HANDOVER_FAILED_AT_ACQUIRE - 資源狀態:保持空閒,由後續請求競爭。MUST NOT 自動恢復源 Session
6.5.3 並行交接請求的序列化
針對同一資源的多個並行交接請求 MUST 被序列化:
- 資源處於
handover_pending期間,新交接請求被排入佇列或拒絕 - 實作 MAY 選擇拒絕(
E_HANDOVER_IN_PROGRESS)或排入佇列(最大佇列長度 8) - 排入佇列的請求按 FIFO 處理,每個請求在前一個交接完成(成功或失敗)後才進入評估
6.6 逾時處理
每次交接 MUST 設定強制逾時。逾時閾值由策略類型決定:
| 策略類型 | 預設逾時 | 範圍 |
|---|---|---|
| 優先級規則指令稿 | 1 秒 | 0.5–2 秒 |
| AI 模型即時判定 | 1 秒 | 0.5–3 秒 |
| 人類使用者決策 | 30 秒 | 5–120 秒 |
6.6.1 逾時回滾原則
若交接在逾時內未完成(即未到達 [T5]),終端 MUST:
- 中止目前正在進行的交接步驟
- 若處於 [T0]–[T2](源未完全終止):回滾到原 Session active 狀態
- 若處於 [T3]–[T4](源已終止):按 §6.5.2 處理(不恢復源,資源置空閒)
- 向相關方傳送
HandoverFailedNotification
6.6.2 逾時通知
HandoverFailedNotification (body of ProtocolMessage) {
required handover_id : uuid
required source_session_id : Session_ID
required target_fay_id : Fay_ID
required reason : enum["timeout", "policy_rejected", "release_failed", "acquire_failed"]
optional details : map<string, string>
}
6.7 重試策略
交接失敗後的重試策略由發起方決定。本規範不強制重試機制,但定義重試的邊界:
- 同一交接請求的重試間隔 SHOULD ≥ 1 秒
- 同一 (source_session, target_fay) 對的重試次數 SHOULD ≤ 3 次
- 重試 MUST 使用新的 handover_id
終端 MAY 拒絕過於頻繁的重試請求並返回 E_HANDOVER_RETRY_LIMIT。
6.8 Fay-to-Human 交接
將控制權歸還給人類使用者的交接遵循上述流程,但目標方為人類使用者:
target_fay_id欄位使用特殊值"human:" + terminal_id(表示目前終端的人類使用者)- 目標授權校驗跳過(人類使用者對自己終端的資源預設有完整權限)
- 策略評估通常使用 §6.4.3 人類使用者決策(確認接管意願)
- 建立目標 Session 時,Session 不繫結到任何 Fay,而是直接由 OS 使用者程序持有
人類使用者主動接管的反向流程對稱:將原 Fay Session 替換為人類持有的 OS 程序。
6.9 交接的可觀測性
終端 MUST 向以下方提供交接事件可觀測性:
| 接收方 | 接收的事件 |
|---|---|
| 源 iFay_Runtime | SessionStateChanged(active → handover_pending → terminating → terminated) |
| 目標 iFay_Runtime | AuthResult(建立新 Session 的成功回應) 或 HandoverFailedNotification |
| 終端稽核日誌 | 完整交接記錄(含 handover_id、source、target、policy 決策、最終結果) |
6.10 交接訊息序列
成功交接的完整訊息序列:
[Source Runtime] [Target Runtime] [Terminal]
│ │ │
│── SessionTransferRequest ─────────────→│
│ │ │── 評估策略
│ │ │── source: active → handover_pending
│←─ SessionStateChanged(handover_pending)│
│ │ │── 終止 source
│←─ SessionStateChanged(terminating)─────│
│←─ SessionStateChanged(terminated)──────│
│ │ │── 建立 target
│ │←─ AuthResult ────│
│ │ │── target: creating → active
│ │←─ SessionStateChanged(active)
失敗回滾的訊息序列:
[Source Runtime] [Target Runtime] [Terminal]
│ │ │
│── SessionTransferRequest ─────────────→│
│ │ │── 評估策略
│ │ │── source: active → handover_pending
│←─ SessionStateChanged(handover_pending)│
│ │ │── 逾時或失敗
│ │ │── source: handover_pending → active
│←─ SessionStateChanged(active)──────────│
│←─ HandoverFailedNotification ──────────│
│ │←─ HandoverFailedNotification
