第 2 章:資料模型

本章定義 CAP 協議中的核心資料結構,包括欄位名稱、類型、約束和預設值。本章中的欄位定義是規範性的——任何符合 CAP 協議的實作 MUST 按本章定義產生和解析這些資料結構。

schema/{version}/schema.json 提供本章資料結構的形式化補充。當 schema.json 與本章描述存在衝突時,以 schema.json 為準。

2.1 資料類型約定

本規範使用以下基礎類型描述欄位:

類型說明編碼
stringUTF-8 字串UTF-8 位元組序列
bytes位元組序列原始位元組
uint32 / uint64無符號整數大端序
timestampUnix 時間戳記(秒)uint64
uuidRFC 4122 UUID v716 位元組
enum列舉值字串字面量
array<T>T 類型元素的有序集合陣列
map<K,V>K 到 V 的對映物件

欄位約束使用以下記號:

  • required:欄位 MUST 出現,值不為 null
  • optional:欄位 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_idrequired, unique本憑證的全域唯一識別碼
issuer_idrequired簽發方識別碼,對應金鑰信任路徑中的 Descriptor_Issuer
subject_fay_idrequired被授權的 Fay 識別碼
terminal_idrequired授權範圍限定的終端識別碼
grantsrequired, 1..256 個元素具體授權項列表(參見 §2.3.4)
issued_atrequired簽發時間
not_beforerequired, ≥ issued_at生效起始時間
not_afterrequired, > not_before失效時間
grantor_idoptional授權人識別碼(Natural_Person 或 Official_Post)
metadataoptional簽發方自訂中繼資料,對協議語意無影響

實作 MUST 拒絕以下條件不滿足的 Authorization_Descriptor:

  1. not_after - not_before > 90 天:本規範限定單份憑證的最長有效期為 90 天
  2. not_before > 目前時間 + 24 小時:禁止簽發過早生效的憑證(防止預簽發濫用)
  3. 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:

  1. 僅支援上述三種語法,拒絕包含其他特殊字元的模式
  2. 萬用字元 * 僅比對單層路徑段
  3. 萬用字元 ** 僅可出現在模式末尾

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 欄位
jtidescriptor_id
ississuer_id
subsubject_fay_id
audterminal_id
iatissued_at
nbfnot_before
expnot_after(但 MUST 不超過 iat + 7 天
grantsgrants

轉換後的 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 協議使用以下序列化格式:

資料結構序列化格式用途
AuthorizationDescriptorRFC 8949 CBOR(確定性編碼)離線儲存與傳輸
Trusted_TicketRFC 7515 JWS Compact Serialization線上傳輸
ProtocolMessageJSON(UTF-8)iFay_Runtime ↔ Protocol_Engine 互動
RevocationStatementRFC 8949 CBOR(確定性編碼)撤銷清單分發

實作 MAY 在 ProtocolMessage 的傳輸層使用 CBOR 取代 JSON 以減少額外負擔,但 schema.json 定義的欄位名稱和語意 MUST 保持一致。