第 4 章 逻辑帧结构

4.1 总体结构

LogicalFrame 必须 由两部分组成:

+----------------+
|     Header     |   (明文)
+----------------+
|     Payload    |   (加密)
+----------------+

LogicalFrame 的形式化定义:

interface LogicalFrame {
  header: FrameHeader;
  payload: Uint8Array;  // 加密
}

4.2 帧头(FrameHeader)

帧头 必须 包含以下字段,以下表中的顺序为规范性顺序:

字段类型必需加密描述
protocolVersionProtocolVersion必需协议版本号
frameTypeFrameType必需帧类型
fragmentIdFragmentID必需Fragment 唯一标识符
agreementIdAgreementID | null必需约定 ID( 为 null)
originTimestampOriginTimestamp必需原始时间戳(UTC ms)
dagDependenciesDAGEdge[]必需DAG 依赖列表( 为空数组)
encryptionMetadataEncryptionMetadata必需加密元数据
sequenceNumberSequenceNumber必需传输序列号

帧头 不得 加密。所有字段 必须 以明文传输。

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,用于压缩传输。压缩规则 必须 遵循以下要求:

  1. 一批连续的、属于同一约定的 Fragment 中, 第一个 Fragment 的帧头 必须 携带完整的 Agreement_ID。
  2. 后续 Fragment 的 agreementId 字段 设为 null,表示沿用上一个非 null 的 Agreement_ID。
  3. 接收方 必须 维护"当前上下文 Agreement_ID",并按以下规则解释:
    • 收到 agreementId 非 null 的 Fragment 时,必须 将其值更新为当前上下文 Agreement_ID。
    • 收到 agreementId 为 null 的 Fragment 时,必须 将其关联到当前上下文 Agreement_ID。
  4. 如接收方收到 agreementId 为 null 但当前上下文 Agreement_ID 也为 null 的 Fragment,必须 丢弃该 Fragment 并返回 AGREEMENT_NOT_FOUND 错误(3001)。
  5. 如接收方收到引用了未知 Agreement_ID 的 Fragment,必须 丢弃该 Fragment 并返回 AGREEMENT_NOT_FOUND 错误(3001)。

接收方的当前上下文 Agreement_ID 必须 为每个传输方向独立维护。

4.6 原始时间戳(Origin_Timestamp)

originTimestamp 必须 满足:

  1. 必须 使用 UTC 时区。
  2. 必须 具有毫秒级精度。
  3. 必须 是非负整数(Unix 时间戳的毫秒数)。
  4. 必须 记录数据在源端实际产生的时刻,不得 是传输时刻。
  5. 经过完整的传输链路(序列化 → 加密 → 传输 → 解密 → 反序列化)后,必须 与发送前完全一致。
  6. 接收方 不得 修改接收到的 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 必须 满足:

  1. 必须 是非负整数。
  2. 必须 在单次会话内单调递增。
  3. 必须 为每个传输方向(数据归集、数据注入)独立维护。
  4. 序列号空间 不得 在两个方向之间共享。
  5. 从 0 或 1 开始。
  6. 如序列号溢出(实现定义的最大值),实现 必须 通过新建会话处理,不得 回绕。

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 中重复 dataTypesource 中已有的信息。

4.12 序列化要求

LogicalFrame 的序列化 必须 满足以下规范性要求:

  1. 确定性:相同的 LogicalFrame 对象 必须 产生相同的二进制输出。
  2. 往返一致性:对于任意有效的 LogicalFrame,序列化后再反序列化 必须 产生与原始对象等价的 LogicalFrame。
  3. 完整性:序列化输出 必须 包含帧头的所有字段。
  4. 载荷加密:在序列化之前,Payload 必须 已经使用 EncryptionMetadata 中指定的算法加密。

序列化的具体二进制布局(字节顺序、字段编码方式)将在后续草案中明确, 优先选择 CBOR(RFC 8949)或 Protocol Buffers 等成熟的二进制格式。

4.13 物理分片

当底层传输需要分片(例如 BLE 的 MTU 限制)时:

  1. 分片操作 必须 由 Transport_Adapter 负责。
  2. LogicalFrame 必须 在 DTP_Engine 层保持完整性。
  3. 接收方的 Transport_Adapter 必须 在传递给 DTP_Engine 之前重组完整的 LogicalFrame。