第 6 章:控制權交接協議

本章定義 Handover_Policy(控制權交接策略)的協議流程,包括三類策略的語意、交接的原子性保證、逾時回滾和通知機制。本章對應藍圖 §2.4 的設計意圖。

6.1 適用場景

控制權交接發生在多個控制方需要先後使用同一 Terminal_Resource 的場景中。本規範定義兩類核心交接:

  1. Fay-to-Fay:一個 Fay 將其持有的 Session 控制權轉移給另一個 Fay
  2. Fay-to-Human:Fay 將控制權歸還給人類使用者,或人類使用者將控制權委託給 Fay

本規範以 Fay-to-Fay 為主要描述對象。Fay-to-Human 交接複用相同流程,將「人類使用者」建模為透過特殊介面直接與終端 OS 互動的實體。

6.2 交接發起

6.2.1 觸發條件

交接由以下場景之一觸發:

  1. 新 Fay 主動請求資源:Fay-B 透過 AuthRequest 請求存取已被 Fay-A 佔用的資源
  2. 現 Fay 主動讓出:Fay-A 透過 SessionTransferRequest 主動請求將控制權交給指定 Fay-B
  3. 管理觸發:人類使用者或管理介面要求轉移控制權

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>
}

評估流程

  1. 終端載入 script_id 對應的規則指令稿
  2. 輸入:源 Session 資訊、目標 Fay 識別、目標憑證 grants、目前時間、Resource_ID 元資料
  3. 輸出:源優先級分數 S_source、目標優先級分數 S_target
  4. 決策: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)
}

評估流程

  1. 終端建構決策請求,包含 source/target 資訊和 context_fields 指定的情境
  2. 呼叫 AI 模型推論端點
  3. 模型返回決策:allow / reject / require_human
  4. 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"]    // 逾時預設動作
}

評估流程

  1. 終端透過 ui_channel 向人類使用者呈現交接請求詳情
  2. 等待使用者輸入:允許 / 拒絕
  3. 逾時 → 按 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:

  1. 中止目前正在進行的交接步驟
  2. 若處於 [T0]–[T2](源未完全終止):回滾到原 Session active 狀態
  3. 若處於 [T3]–[T4](源已終止):按 §6.5.2 處理(不恢復源,資源置空閒)
  4. 向相關方傳送 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_RuntimeSessionStateChanged(active → handover_pending → terminating → terminated)
目標 iFay_RuntimeAuthResult(建立新 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