编码传递与中途截取
发件人把一份编码消息寄给一位收件人。中继经手人在途中复制了这份消息,完整读过副本,但手里的 密钥解不开它。收件人收到原件后,委托一位持有正确密钥的人代为解读,再把解读结果开放给一名复核者。
这个示例回答的问题是:“拿到副本”“读过”“读懂”这三件事怎样分开记录?替别人完成的解读又怎样记录, 才能让重放直接复用已记录的结果?
所有持有人、时间和内容代码都是合成的测试值。
示例涉及的引擎部件
Section titled “示例涉及的引擎部件”canwu-information,负责信息流转的模拟领域扩展,以及它的规划入口InformationLifecycle::plan。- 同内容副本:第二个
Representation(表现形式),使用ContentRelation::SameContent,并有一条 指向原件的父边。 - 状态为
InterpretationStatus::Failed和Succeeded的Interpretation(解读)记录,每条都绑定 它所读的访问记录和表现形式。 - 委托解读:
InterpretationAuthority::Delegated引用一条已持久化的命令,命令中带有DelegationClaimV1。 - 每条只面向一个持有人的知识发布(持有人相对知识),以及通过
InformationPlugin完成的快照恢复、精确重放和紧凑检查点恢复。
cargo run -p canwu-information --example encoded_interception所有检查通过后,程序打印一行结果;任何一项检查失败,程序都会提前停止:
encoded_interception: in-transit copy, failed access interpretation, delegated decode, restricted review release, authoritative save/load, exact replay without external decoding, and compact reconstruction verified每个短语对应源码中的一组检查;最后三项来自 examples/support/mod.rs 中的
verify_authoritative_operation_roundtrip,委托解读和复核发布各运行一次。
查看图表源码
sequenceDiagram
participant S as 发件人 H-601
participant R as 经手人 H-603
participant P as 收件人 H-602
participant D as 受托解读者 H-604
participant V as 复核者 H-605
S->>R: 发往 H-602,投递尝试 InTransit(第 2–4 分钟)
Note over R: 复制出 SameContent 副本(第 5 分钟)
R->>R: 阅读副本,decode_k1 解读失败(第 6–7 分钟)
R->>P: 投递尝试 Delivered,收件人阅读(第 12–13 分钟)
Note over P,D: 委托声明,能力 decode_k2
D-->>P: 解读成功,生成结果内容(第 14–15 分钟)
P->>V: 复核发布转为 Active(第 17–19 分钟)
场景代码在
encoded_interception.rs,
共用的辅助函数在
support/mod.rs。
和机密副本与定向发布一样,记录是逐条请求在脱离
运行时的账本上规划出来的。
| 持有人 | 角色 |
|---|---|
H-601 |
发件人 |
H-602 |
指定收件人,委托解读并发布复核结果 |
H-603 |
中继经手人,复制消息并尝试解读 |
H-604 |
替 H-602 解读的受托人 |
H-605 |
复核者 |
1. 编码并发送(第 0–4 分钟)
Section titled “1. 编码并发送(第 0–4 分钟)”原始表现形式写明了读懂它需要的能力:
payload: RepresentationPayload { format: "grouped_symbols_v1".to_owned(), created_at: minute(1), operation: "encode_k2".to_owned(), content_relation: ContentRelation::SameContent, sources: Vec::new(), claimed_source: None, interpretation_capability: Some("decode_k2".to_owned()),},发往 H-602 的定向 Dispatch 转为 Active。它的 DeliveryAttempt(投递尝试)以 relay
角色记下 H-603,并转为 InTransit。
2. 经手人复制消息(第 5 分钟)
Section titled “2. 经手人复制消息(第 5 分钟)”经手人为同一份内容创建第二个表现形式:
content_relation: ContentRelation::SameContent,sources: vec![RepresentationSourceEdge { parent: encoded.clone(), completeness_per_mille: 1_000, fidelity_per_mille: 1_000,}],SameContent 要求副本与父表现形式引用同一条 Content 记录(validate_representation_lineage)。
经手人还为副本创建了自己保管的 Instance。
3. 经手人读了副本,却没能解读(第 6–7 分钟)
Section titled “3. 经手人读了副本,却没能解读(第 6–7 分钟)”经手人的访问引用截取得到的载体实例,并完整读过副本(extent_per_mille: 1_000)。他的解读记录:
payload: InterpretationPayload { interpreted_at: minute(7), status: InterpretationStatus::Failed, capability: "decode_k1".to_owned(), confidence_per_mille: 0, authenticity: None,},authority: InterpretationAuthority::HolderSelf,Failed 这个结果由示例给出。扩展把 capability 和 interpretation_capability 当作标签保存,
解读能否成功由你的应用判断。扩展检查的是结果的记录方式(见
lifecycle.rs
中的 validate_interpretation):
- 每条解读都要有
input_access、input_representation、performed_by和performed_for引用,且每个输入表现形式都必须是某条输入访问读过的; Failed的解读不带result_content,Partial或Succeeded的解读必须带;- 使用
HolderSelf时,执行者与服务对象必须是同一个持有人。
示例直接验证了第二条规则:缺少 result_content 的 Succeeded 请求必须失败。
assert!(ledger.plan(&invalid_success_without_result).is_err());4. 原件送达(第 12–13 分钟)
Section titled “4. 原件送达(第 12–13 分钟)”投递尝试转为 Delivered,并向 H-602 发布 RepresentationAvailable。收件人的访问引用
delivery_attempt、dispatch 和原始表现形式;经手人的访问引用的是截取得到的载体实例,两次阅读
各有各的证据。
5. 受托人替收件人解读(第 14–15 分钟)
Section titled “5. 受托人替收件人解读(第 14–15 分钟)”解读结果是从原件衍生出的新内容,代码为 SYN-E8-42-R。成功的解读把 H-604 记为执行者、H-602
记为服务对象,并绑定结果:
holder_reference("performed_by", &performer_holder),holder_reference("performed_for", &destination_holder),DomainReference::from_typed("result_content", decoded_content.clone()),它的权限来自委托:
authority: InterpretationAuthority::Delegated { evidence: EvidenceRef::Command(CommandId::new(1)), authority_grant: DELEGATED_AUTHORITY_GRANT.to_owned(),},授权代码 DELEGATED_AUTHORITY_GRANT(interpret_for_holder)告诉 InformationPlugin:到发给
canwu-authority 的 delegate_interpretation_v1 插件命令中,按 claim 键读取委托声明。示例里,
support/mod.rs 中的 CaseAuthorityPlugin 注册了这条命令,权威运行中的第一条命令携带如下声明:
Some(DelegationClaimV1 { format_version: 1, performed_by: EntityRef::Person(PersonId::new(604)), performed_for: destination_holder.clone(), capabilities: vec!["decode_k2".to_owned()], not_before: Some(SimTime::EPOCH), expires_at: None,}),应用这条解读时,插件检查声明是否写明了这个执行者、这个服务对象和这项能力,以及解读时间是否落在
[not_before, expires_at) 之内。检查不通过,操作就以 invalid_authority 被拒绝。
权威运行结束后,只有收件人得到新的知识:
assert_authoritative_knowledge( canwu, &destination_holder, &["interpretation_recorded"],)?;assert_authoritative_knowledge(canwu, &review_holder, &[])?;assert_authoritative_knowledge(canwu, &source_holder, &[])?;assert_authoritative_knowledge(canwu, &performer_holder, &[])重放时,辅助函数用 PersistedResultReplayPlugin 代替 CaseAuthorityPlugin。它对同一条命令的
处理函数只接受已经带有记录结果的载荷,否则以 ReplayMismatch 失败;因此重放通过,就说明结果来自
日志。
6. 把结果开放给复核者(第 16–19 分钟)
Section titled “6. 把结果开放给复核者(第 16–19 分钟)”受托人把结果渲染成 review_text_v1 表现形式。接着,H-602 创建由 H-602 和 H-605 组成的
显式受众,并为这个表现形式创建面向受众的发布。激活同样在 Canwu 中执行一遍:
assert_authoritative_knowledge(canwu, &destination_holder, &["release_available"])?;assert_authoritative_knowledge(canwu, &review_holder, &["release_available"])?;assert_authoritative_knowledge(canwu, &source_holder, &[])?;assert_authoritative_knowledge(canwu, &performer_holder, &[])值得注意的地方
Section titled “值得注意的地方”- 副本、访问和解读是三条独立的记录。经手人手里有完整副本,也完整读过,却仍然没有解读结果。
- 解读成败是应用输入。扩展规定的是结果怎样记录,包括结果内容的绑定。
- 委托解读只向服务对象发布知识,受托人不会因此得到任何知识。
- 委托声明保存在已持久化的命令里,重放时直接从日志核验权限。
- 在经手人那条失败的解读中加入
DomainReference::from_typed("result_content", content.clone())。 规划会失败,报错failed interpretation cannot have result content。 - 把经手人那条解读的
performed_for改成destination_holder,权限仍用HolderSelf。规划会失败, 报错self interpretation authority requires performer and holder equality。 - 把
DelegationClaimV1的capabilities改成vec!["decode_k1".to_owned()]。脱离运行时的 规划仍会成功,但InformationPlugin以invalid_authority拒绝该操作,示例停止并报错authoritative case operation did not complete: Rejected。
判断声称的来源
Section titled “判断声称的来源”表现形式可以在 RepresentationPayload::claimed_source 中写明它声称的来源;对它的解读随后可以在
InterpretationPayload::authenticity 中记录一条真伪判定
(AuthenticityFinding):是否接受声称的来源、一个简短的 basis(例如 "seal_mismatch"),以及
置信度。判定必须引用这次解读所读、并且带有 claimed_source 的表现形式的当前版本,否则
InformationPlugin 以 invalid_lifecycle 拒绝该操作。这样,一份伪造的文书可以记为“已经解读”,
同时不接受它声称的发送者。持有人识破伪造的概率由应用抽样决定(见模型归属),
本示例中 authenticity 为 None,真伪判定测试构造了一条这样的判定。
来自指派角色的权限
Section titled “来自指派角色的权限”InterpretationAuthority::InstitutionalRole 与委托形式类似,但它按授权代码
interpret_as_assigned_role,从某条 AuthorityAssignment 记录的确切版本中读取声明。
打开可运行示例
阅读示例共用的辅助函数
阅读解读权限测试
阅读真伪判定测试