第 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。
