第 2 章:数据模型
本章定义 CAP 协议中的核心数据结构,包括字段名称、类型、约束和默认值。本章中的字段定义是规范性的——任何符合 CAP 协议的实现 MUST 按本章定义生成和解析这些数据结构。
schema/{version}/schema.json 提供本章数据结构的形式化补充。当 schema.json 与本章描述存在冲突时,以 schema.json 为准。
2.1 数据类型约定
本规范使用以下基础类型描述字段:
| 类型 | 说明 | 编码 |
|---|---|---|
string | UTF-8 字符串 | UTF-8 字节序列 |
bytes | 字节序列 | 原始字节 |
uint32 / uint64 | 无符号整数 | 大端序 |
timestamp | Unix 时间戳(秒) | uint64 |
uuid | RFC 4122 UUID v7 | 16 字节 |
enum | 枚举值 | 字符串字面量 |
array<T> | T 类型元素的有序集合 | 数组 |
map<K,V> | K 到 V 的映射 | 对象 |
字段约束使用以下记号:
required:字段 MUST 出现,值不为 nulloptional:字段 MAY 出现,缺省视为未设置unique:字段值在系统范围内唯一len(N..M):字符串/字节长度在 N 到 M 之间(含端点)regex(...):字段值 MUST 匹配指定正则表达式
2.2 标识符
CAP 协议中的核心标识符 MUST 满足全局唯一性。本节定义各类标识符的格式与生成规则。
2.2.1 Fay_ID
Fay_ID 唯一标识一个 Fay 实例。
| 属性 | 取值 |
|---|---|
| 类型 | string |
| 格式 | "fay:" + uuid_v7 |
| 长度 | 40 字符(含前缀) |
| 唯一性 | 全局唯一 |
| 生成方 | 身份管理子系统(不在 CAP 协议范围) |
示例:fay:01927b34-7e21-7c4d-a89f-1234567890ab
2.2.2 Terminal_ID
Terminal_ID 唯一标识一个终端设备。
| 属性 | 取值 |
|---|---|
| 类型 | string |
| 格式 | "terminal:" + uuid_v7 |
| 长度 | 45 字符(含前缀) |
| 唯一性 | 全局唯一 |
| 生成方 | Registration_Authority |
2.2.3 Resource_ID
Resource_ID 标识终端上的一个具体资源。
| 属性 | 取值 |
|---|---|
| 类型 | string |
| 格式 | terminal_id + "/" + resource_path |
| 长度 | 最长 256 字符 |
| 唯一性 | 终端范围内唯一 |
| 生成方 | 终端操作系统 |
resource_path MUST 满足正则 ^[a-zA-Z0-9._\-/]+$。
示例:terminal:01927b34-.../device/camera/front
2.2.4 Descriptor_ID
Descriptor_ID 唯一标识一份 Authorization_Descriptor。
| 属性 | 取值 |
|---|---|
| 类型 | uuid |
| 格式 | UUID v7 |
| 唯一性 | 全局唯一(在所有 Descriptor_Issuer 范围内) |
| 生成方 | Descriptor_Issuer |
撤销列表使用 Descriptor_ID 标识被撤销的凭证。Descriptor_Issuer MUST NOT 复用已使用过的 Descriptor_ID。
2.2.5 Session_ID
Session_ID 唯一标识一个活跃会话。
| 属性 | 取值 |
|---|---|
| 类型 | uuid |
| 格式 | UUID v7 |
| 唯一性 | 终端范围内唯一 |
| 生成方 | 终端 Protocol_Engine |
| 生命周期 | 仅在会话活跃期间有效,会话终止后该 ID 不复用 |
2.3 Authorization_Descriptor
Authorization_Descriptor 是离线授权的核心数据结构。一份 Authorization_Descriptor 由两部分组成:载荷(payload) 和 签名(signature)。
2.3.1 顶层结构
AuthorizationDescriptor {
required version : uint32
required payload : DescriptorPayload
required signature : DescriptorSignature
}
| 字段 | 说明 |
|---|---|
version | 协议版本号,v1 实现 MUST 设为 1 |
payload | 授权信息载荷(参见 §2.3.2) |
signature | 对 payload 的数字签名(参见 §2.3.3) |
2.3.2 DescriptorPayload
DescriptorPayload {
required descriptor_id : Descriptor_ID
required issuer_id : string
required subject_fay_id : Fay_ID
required terminal_id : Terminal_ID
required grants : array<Grant> (len 1..256)
required issued_at : timestamp
required not_before : timestamp
required not_after : timestamp
optional grantor_id : string
optional metadata : map<string, string>
}
| 字段 | 约束 | 说明 |
|---|---|---|
descriptor_id | required, unique | 本凭证的全局唯一标识 |
issuer_id | required | 签发方标识,对应密钥信任路径中的 Descriptor_Issuer |
subject_fay_id | required | 被授权的 Fay 标识 |
terminal_id | required | 授权范围限定的终端标识 |
grants | required, 1..256 个元素 | 具体授权项列表(参见 §2.3.4) |
issued_at | required | 签发时间 |
not_before | required, ≥ issued_at | 生效起始时间 |
not_after | required, > not_before | 失效时间 |
grantor_id | optional | 授权人标识(Natural_Person 或 Official_Post) |
metadata | optional | 签发方自定义元数据,对协议语义无影响 |
实现 MUST 拒绝以下条件不满足的 Authorization_Descriptor:
not_after - not_before > 90 天:本规范限定单份凭证的最长有效期为 90 天not_before > 当前时间 + 24 小时:禁止签发过早生效的凭证(防止预签发滥用)grants数组为空:无授权项的凭证无意义
2.3.3 DescriptorSignature
DescriptorSignature {
required algorithm : enum["ed25519", "ecdsa-p256-sha256"]
required key_id : string
required signature_value : bytes
}
| 字段 | 说明 |
|---|---|
algorithm | 签名算法,参见第 8 章 |
key_id | 用于签名的密钥标识,对应 Verification_Key 标识 |
signature_value | 对 payload 的 CBOR 序列化字节进行签名的结果 |
签名输入:将 DescriptorPayload 按 RFC 8949 CBOR 确定性编码(Deterministic Encoding)序列化为字节序列,作为签名算法的输入。
2.3.4 Grant
Grant {
required resource_pattern : string
required modes : array<AccessMode> (len 1..4)
optional constraints : map<string, string>
}
| 字段 | 说明 |
|---|---|
resource_pattern | 资源匹配模式(参见 §2.3.5) |
modes | 授权的访问模式列表,元素类型 AccessMode |
constraints | 附加约束(如时间窗口、地理围栏等),对协议语义的影响参见第 7 章 |
2.3.5 资源匹配模式
resource_pattern 支持以下匹配语法:
- 精确匹配:
terminal:xxx/device/camera/front - 通配符匹配:
terminal:xxx/device/camera/*(匹配该终端下所有摄像头) - 全终端匹配:
terminal:xxx/device/camera/**(匹配该路径下所有层级)
实现 MUST:
- 仅支持上述三种语法,拒绝包含其他特殊字符的模式
- 通配符
*仅匹配单层路径段 - 通配符
**仅可出现在模式末尾
2.3.6 AccessMode
AccessMode = enum["read", "write", "execute", "configure"]
各访问模式的语义参见第 7 章。
2.4 Trusted_Ticket
Trusted_Ticket 是在线授权凭证。其结构基于 RFC 7515 JWS Compact Serialization。
2.4.1 顶层结构
Trusted_Ticket 是一个 JWS 字符串,由三部分用 . 分隔:
base64url(header) . base64url(payload) . base64url(signature)
2.4.2 Header
TicketHeader {
required alg : enum["EdDSA", "ES256"]
required typ : "cap-ticket+jws"
required kid : string
}
| 字段 | 说明 |
|---|---|
alg | 签名算法(与 §8 一致) |
typ | 固定值 "cap-ticket+jws",用于区分票据类型 |
kid | 密钥标识,用于校验签名 |
2.4.3 Payload
TicketPayload {
required jti : uuid // 票据唯一 ID
required iss : string // Ticket_Issuer 标识
required sub : Fay_ID // 被授权的 Fay
required aud : Terminal_ID // 目标终端
required iat : timestamp // 签发时间
required nbf : timestamp // 生效起始时间
required exp : timestamp // 失效时间
required grants : array<Grant> // 与 §2.3.4 同结构
optional convertible : boolean (default true) // 是否可转换为 Authorization_Descriptor
}
实现 MUST 拒绝 exp - nbf > 7 天 的 Trusted_Ticket。在线票据的最长有效期短于离线授权,以确保在线撤销机制能够及时生效。
2.4.4 Trusted_Ticket 到 Authorization_Descriptor 的转换
当 convertible == true 时,终端 MAY 将 Trusted_Ticket 转换为本地 Authorization_Descriptor 格式以供离线使用。转换规则:
| TicketPayload 字段 | 映射到 DescriptorPayload 字段 |
|---|---|
jti | descriptor_id |
iss | issuer_id |
sub | subject_fay_id |
aud | terminal_id |
iat | issued_at |
nbf | not_before |
exp | not_after(但 MUST 不超过 iat + 7 天) |
grants | grants |
转换后的 Authorization_Descriptor 由终端使用其本地存储密钥重新签名,签名 key_id 标记为转换来源(参见第 4 章)。原始 Trusted_Ticket 的签名信息 MUST 保留在 metadata 中以备审计。
2.5 Session
Session 是终端内部的会话状态结构,不通过协议消息传输完整结构。本节定义 Session 的字段以便规范状态机和接口约定。
Session {
required session_id : Session_ID
required fay_id : Fay_ID
required runtime_id : string
required resource_id : Resource_ID
required access_mode : AccessMode
required granted_modes : array<AccessMode>
required state : SessionState
required created_at : timestamp
required last_heartbeat_at : timestamp
required credential_ref : CredentialRef
}
SessionState = enum[
"creating",
"active",
"handover_pending",
"terminating",
"terminated"
]
CredentialRef {
required type : enum["descriptor", "ticket"]
required id : string // descriptor_id 或 jti
required not_after : timestamp
}
SessionState 状态机参见第 5 章。
2.6 协议消息封装
iFay_Runtime 与 Protocol_Engine 之间的所有消息共享以下封装结构:
ProtocolMessage {
required version : uint32 (= 1)
required message_id : uuid
required message_type : string
required timestamp : timestamp
required sender_id : string
required body : object
optional correlation_id : uuid
}
| 字段 | 说明 |
|---|---|
version | 协议版本号,v1 设为 1 |
message_id | 本消息的唯一标识 |
message_type | 消息类型字面量(如 "AuthRequest") |
timestamp | 消息发送时间 |
sender_id | 发送方标识(runtime_id 或 terminal_id) |
body | 消息体,结构由 message_type 决定 |
correlation_id | 关联的请求消息 ID(响应消息 MUST 设置此字段) |
各 message_type 对应的 body 结构在相应章节定义。
2.7 Verification_Key
Verification_Key 是终端持有的签名校验密钥。
VerificationKey {
required key_id : string
required algorithm : enum["ed25519", "ecdsa-p256-sha256"]
required key_material : bytes // 公钥字节
required issuer_id : string // 该密钥对应的签发方标识
required valid_from : timestamp
optional valid_until : timestamp
required source : enum["pre-installed", "ra-distributed"]
}
| 字段 | 说明 |
|---|---|
key_id | 密钥标识,与 DescriptorSignature.key_id 对应 |
algorithm | 该密钥支持的签名算法 |
key_material | 公钥的原始字节,编码方式由 algorithm 决定(参见第 8 章) |
issuer_id | 该密钥对应的 Descriptor_Issuer 标识 |
valid_from | 密钥生效起始时间 |
valid_until | 密钥失效时间,未设置表示长期有效 |
source | 密钥来源:pre-installed(终端出厂预置)或 ra-distributed(Registration_Authority 在线分发) |
终端 MUST 安全存储所有 Verification_Key(参见第 8 章)。
2.8 撤销声明
撤销声明用于通知终端某份凭证已被撤销。
RevocationStatement {
required version : uint32 (= 1)
required revocation_id : uuid
required target_descriptor_id : Descriptor_ID
required issuer_id : string
required revoked_at : timestamp
optional reason : enum["unspecified", "compromised", "superseded", "no_longer_needed"]
required signature : DescriptorSignature
}
撤销声明 MUST 由原始 Authorization_Descriptor 的 issuer_id 签发并签名。
2.9 序列化与传输
CAP 协议使用以下序列化格式:
| 数据结构 | 序列化格式 | 用途 |
|---|---|---|
| AuthorizationDescriptor | RFC 8949 CBOR(确定性编码) | 离线存储与传输 |
| Trusted_Ticket | RFC 7515 JWS Compact Serialization | 在线传输 |
| ProtocolMessage | JSON(UTF-8) | iFay_Runtime ↔ Protocol_Engine 交互 |
| RevocationStatement | RFC 8949 CBOR(确定性编码) | 撤销列表分发 |
实现 MAY 在 ProtocolMessage 的传输层使用 CBOR 替代 JSON 以减少开销,但 schema.json 定义的字段名称和语义 MUST 保持一致。
