第 4 章 邏輯訊框結構
4.1 整體結構
LogicalFrame 必須 由兩部分組成:
+----------------+
| Header | (明文)
+----------------+
| Payload | (加密)
+----------------+
LogicalFrame 的形式化定義:
interface LogicalFrame {
header: FrameHeader;
payload: Uint8Array; // 加密
}
4.2 訊框標頭(FrameHeader)
訊框標頭 必須 包含以下欄位,以下表中的順序為規範性順序:
| 欄位 | 類型 | 必需 | 加密 | 描述 |
|---|---|---|---|---|
protocolVersion | ProtocolVersion | 必需 | 否 | 協定版本號 |
frameType | FrameType | 必需 | 否 | 訊框類型 |
fragmentId | FragmentID | 必需 | 否 | Fragment 唯一識別碼 |
agreementId | AgreementID | null | 必需 | 否 | 約定 ID(可 為 null) |
originTimestamp | OriginTimestamp | 必需 | 否 | 原始時間戳記(UTC ms) |
dagDependencies | DAGEdge[] | 必需 | 否 | DAG 依賴清單(可 為空陣列) |
encryptionMetadata | EncryptionMetadata | 必需 | 否 | 加密中繼資料 |
sequenceNumber | SequenceNumber | 必需 | 否 | 傳輸序列號 |
訊框標頭 不得 加密。所有欄位 必須 以明文傳輸。
4.3 訊框類型(FrameType)
FrameType 必須 是以下四個列舉值之一:
| 值 | 用途 | Payload 內容 |
|---|---|---|
"data" | 承載實際的 Fragment 資料 | Fragment 的 data 欄位 |
"request" | 發起資料請求或調整傳輸約定 | RequestFrame 的序列化內容 |
"response" | 回覆資料請求 | ResponseFrame 的序列化內容 |
"control" | 傳遞錯誤通知、約定終止等控制資訊 | ControlFrame 的序列化內容 |
實作 不得 引入未列出的訊框類型。
4.4 協定版本(ProtocolVersion)
ProtocolVersion 必須 由兩個非負整數組成:
interface ProtocolVersion {
major: number;
minor: number;
}
版本號語義與變更判定規則 必須 遵循第 1 章 §1.7.2 定義的規則(權威來源)。
4.5 Agreement_ID 壓縮
agreementId 欄位 可 為 null,用於壓縮傳輸。壓縮規則 必須 遵循以下要求:
- 一批連續的、屬於同一約定的 Fragment 中,僅 第一個 Fragment 的訊框標頭 必須 攜帶完整的 Agreement_ID。
- 後續 Fragment 的
agreementId欄位 可 設為null,表示沿用上一個非 null 的 Agreement_ID。 - 接收方 必須 維護「當前上下文 Agreement_ID」,並按以下規則解釋:
- 收到
agreementId非 null 的 Fragment 時,必須 將其值更新為當前上下文 Agreement_ID。 - 收到
agreementId為 null 的 Fragment 時,必須 將其關聯到當前上下文 Agreement_ID。
- 收到
- 如接收方收到
agreementId為 null 但當前上下文 Agreement_ID 也為 null 的 Fragment,必須 丟棄該 Fragment 並返回AGREEMENT_NOT_FOUND錯誤(3001)。 - 如接收方收到引用了未知 Agreement_ID 的 Fragment,必須 丟棄該 Fragment 並返回
AGREEMENT_NOT_FOUND錯誤(3001)。
接收方的當前上下文 Agreement_ID 必須 為每個傳輸方向獨立維護。
4.6 原始時間戳記(Origin_Timestamp)
originTimestamp 必須 滿足:
- 必須 使用 UTC 時區。
- 必須 具有毫秒級精度。
- 必須 是非負整數(Unix 時間戳記的毫秒數)。
- 必須 記錄資料在來源端實際產生的時刻,不得 是傳輸時刻。
- 經過完整的傳輸鏈路(序列化 → 加密 → 傳輸 → 解密 → 反序列化)後,必須 與傳送前完全一致。
- 接收方 不得 修改接收到的 Origin_Timestamp。
4.7 DAG 依賴(DAGEdge)
DAGEdge 必須 包含以下欄位:
interface DAGEdge {
targetFragmentId: FragmentID;
relationType: DAGRelationType;
}
DAGRelationType 必須 是以下三個列舉值之一:
| 值 | 語義 |
|---|---|
"derived_from" | 該 Fragment 衍生自目標 Fragment |
"annotates" | 該 Fragment 註釋/解釋目標 Fragment |
"supersedes" | 該 Fragment 取代目標 Fragment |
dagDependencies 陣列 可 為空(即 Fragment 沒有依賴關係)。
4.8 加密中繼資料(EncryptionMetadata)
EncryptionMetadata 必須 包含以下欄位:
interface EncryptionMetadata {
algorithm: string;
keyVersion: number;
}
| 欄位 | 規範性要求 |
|---|---|
algorithm | 必須 為加密演算法的識別字串(例如 "AES-256-GCM")。應 使用 IANA 註冊的演算法名 |
keyVersion | 必須 為非負整數。用於支援金鑰輪替 |
加密中繼資料本身 不得 加密,必須 以明文形式包含在訊框標頭中。
4.9 序列號(Sequence_Number)
sequenceNumber 必須 滿足:
- 必須 是非負整數。
- 必須 在單次會話內單調遞增。
- 必須 為每個傳輸方向(資料歸集、資料注入)獨立維護。
- 序列號空間 不得 在兩個方向之間共用。
- 應 從 0 或 1 開始。
- 如序列號溢位(實作定義的最大值),實作 必須 透過新建會話處理,不得 回繞。
4.10 Fragment 結構
Fragment 必須 包含以下欄位:
interface Fragment {
fragmentId: FragmentID;
agreementId: AgreementID;
originTimestamp: OriginTimestamp;
contextMetadata: ContextMetadata;
dagDependencies: DAGEdge[];
data: Uint8Array;
}
註:Fragment 中的 agreementId 欄位在序列化為 LogicalFrame 時,可能因壓縮規則而在 LogicalFrame 標頭中表現為 null(參見第 4.5 節),但 Fragment 本身的邏輯 agreementId 必須 始終非 null。
4.11 上下文中繼資料(ContextMetadata)
ContextMetadata 必須 包含以下欄位:
interface ContextMetadata {
dataType: string;
source: DataSource;
customFields: Record<string, unknown>;
}
DataSource 必須 是以下兩種結構之一(discriminated union,由 kind 欄位區分):
4.11.1 HardwareSource
當資料來源於硬體感測器時,source 必須 為:
interface HardwareSource {
kind: "hardware";
sensorType: string;
precision: string;
samplingRate: number;
}
| 欄位 | 規範性要求 |
|---|---|
kind | 必須 為字面量字串 "hardware" |
sensorType | 必須 為非空字串。應 使用標準化命名(例如 "accelerometer"、"heart_rate_monitor") |
precision | 必須 為非空字串,描述感測器精度(例如 "±0.1°C") |
samplingRate | 必須 為正數,單位為 Hz |
4.11.2 SoftwareSource
當資料來源於軟體共享時,source 必須 為:
interface SoftwareSource {
kind: "software";
appIdentifier: string;
sharingMethod: string;
}
| 欄位 | 規範性要求 |
|---|---|
kind | 必須 為字面量字串 "software" |
appIdentifier | 必須 為非空字串。應 使用反向網域名稱格式(例如 "com.example.app") |
sharingMethod | 必須 為非空字串,描述共享方式(例如 "api_push"、"clipboard_capture") |
4.11.3 自訂欄位
customFields 必須 是字串到任意值的對映,可 為空物件 {}。實作 不得 在 customFields 中重複 dataType 或 source 中已有的資訊。
4.12 序列化要求
LogicalFrame 的序列化 必須 滿足以下規範性要求:
- 確定性:相同的 LogicalFrame 物件 必須 產生相同的二進位輸出。
- 往返一致性:對於任意有效的 LogicalFrame,序列化後再反序列化 必須 產生與原始物件等價的 LogicalFrame。
- 完整性:序列化輸出 必須 包含訊框標頭的所有欄位。
- 負載加密:在序列化之前,Payload 必須 已經使用 EncryptionMetadata 中指定的演算法加密。
序列化的具體二進位佈局(位元組順序、欄位編碼方式)將在後續草案中明確,應 優先選擇 CBOR(RFC 8949)或 Protocol Buffers 等成熟的二進位格式。
4.13 實體分片
當底層傳輸需要分片(例如 BLE 的 MTU 限制)時:
- 分片操作 必須 由 Transport_Adapter 負責。
- LogicalFrame 必須 在 DTP_Engine 層保持完整性。
- 接收方的 Transport_Adapter 必須 在傳遞給 DTP_Engine 之前重組完整的 LogicalFrame。
