640 lines
21 KiB
Rust
640 lines
21 KiB
Rust
//! Native adapter for GH-CHANNEL-RECEIPT-0001.
|
|
//! Language, authorization, execution, verification and reception remain
|
|
//! separate. A model response can never become reality evidence by itself.
|
|
|
|
use ring::digest::{digest, SHA256};
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json::{json, Value};
|
|
use std::collections::{BTreeSet, HashSet};
|
|
use std::fs;
|
|
use std::io::Write;
|
|
use std::path::PathBuf;
|
|
use tauri::AppHandle;
|
|
|
|
const SCHEMA: &str = "guanghu.channel-receipt/v1";
|
|
const CONTRACT_ID: &str = "GH-CHANNEL-RECEIPT-0001";
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
|
pub struct ChannelEvidence {
|
|
pub r#type: String,
|
|
pub r#ref: String,
|
|
#[serde(default)]
|
|
pub verified: bool,
|
|
#[serde(default)]
|
|
pub external: bool,
|
|
#[serde(default)]
|
|
pub proves: Vec<String>,
|
|
#[serde(default)]
|
|
pub does_not_prove: Vec<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
|
pub struct ChannelAuthorization {
|
|
pub current: bool,
|
|
pub scoped: bool,
|
|
pub unexpired: bool,
|
|
pub r#ref: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
|
pub struct ChannelParallelStates {
|
|
pub session: String,
|
|
pub broadcast: String,
|
|
pub handoff: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
|
pub struct ChannelHandoffAcceptance {
|
|
pub target_acceptance: bool,
|
|
pub target_id: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize)]
|
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
|
pub struct CompileChannelReceiptInput {
|
|
pub event_id: String,
|
|
pub channel_id: String,
|
|
pub channel_mode: String,
|
|
pub source_layer: String,
|
|
pub actor_id: String,
|
|
pub intent: String,
|
|
pub claim_layer: String,
|
|
#[serde(default)]
|
|
pub required_proof: Vec<String>,
|
|
#[serde(default)]
|
|
pub evidence: Vec<ChannelEvidence>,
|
|
pub authorization: Option<ChannelAuthorization>,
|
|
pub current_states: Option<ChannelParallelStates>,
|
|
pub prior_receipt_id: Option<String>,
|
|
pub handoff: Option<ChannelHandoffAcceptance>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ChannelReceipt {
|
|
pub schema: &'static str,
|
|
pub contract_id: &'static str,
|
|
pub receipt_id: String,
|
|
pub event_id: String,
|
|
pub received: bool,
|
|
pub identified: Option<String>,
|
|
pub channel: Value,
|
|
pub intent: String,
|
|
pub claim: Value,
|
|
pub affected_layer: String,
|
|
pub effect: String,
|
|
pub reality_status: String,
|
|
pub evidence: Vec<ChannelEvidence>,
|
|
pub required_proof: Vec<String>,
|
|
pub states: Value,
|
|
pub supersedes: Vec<String>,
|
|
pub boundaries: Vec<String>,
|
|
pub next_step: String,
|
|
pub previous_ledger_hash: String,
|
|
pub ledger_receipt_hash: String,
|
|
}
|
|
|
|
pub fn compile(
|
|
app: AppHandle,
|
|
input: CompileChannelReceiptInput,
|
|
) -> Result<ChannelReceipt, String> {
|
|
let mut receipt = compile_pure(input)?;
|
|
let path = ledger_path(&app)?;
|
|
let previous = last_hash(&path)?;
|
|
receipt.previous_ledger_hash = previous.clone();
|
|
let material = serde_json::to_vec(&json!({
|
|
"receiptId": receipt.receipt_id,
|
|
"eventId": receipt.event_id,
|
|
"effect": receipt.effect,
|
|
"realityStatus": receipt.reality_status,
|
|
"boundaries": receipt.boundaries,
|
|
"previousLedgerHash": previous
|
|
}))
|
|
.map_err(|error| format!("HOLOLAKE_CHANNEL_RECEIPT_INVALID: {error}"))?;
|
|
receipt.ledger_receipt_hash = sha256(&material);
|
|
append(&path, &receipt)?;
|
|
Ok(receipt)
|
|
}
|
|
|
|
fn compile_pure(input: CompileChannelReceiptInput) -> Result<ChannelReceipt, String> {
|
|
for (label, value) in [
|
|
("eventId", input.event_id.as_str()),
|
|
("channelId", input.channel_id.as_str()),
|
|
("actorId", input.actor_id.as_str()),
|
|
] {
|
|
if value.trim().is_empty() || value.chars().count() > 512 {
|
|
return Err(format!("HOLOLAKE_CHANNEL_RECEIPT_{label}_INVALID"));
|
|
}
|
|
}
|
|
ensure_member(
|
|
&input.source_layer,
|
|
&[
|
|
"HUMAN_DIRECT_LANGUAGE",
|
|
"MODEL_RESPONSE",
|
|
"LATER_CORRECTION",
|
|
"REALITY_EVIDENCE",
|
|
],
|
|
"SOURCE_LAYER",
|
|
)?;
|
|
ensure_member(
|
|
&input.claim_layer,
|
|
&[
|
|
"LANGUAGE_ONTOLOGY",
|
|
"LANGUAGE_SIMULATION",
|
|
"ENGINEERING_PROPOSAL",
|
|
"REALITY_CLAIM",
|
|
],
|
|
"CLAIM_LAYER",
|
|
)?;
|
|
ensure_member(
|
|
&input.channel_mode,
|
|
&[
|
|
"CONVERSATION_ONLY",
|
|
"LANGUAGE_ARCHITECTURE",
|
|
"REALITY_EXECUTION",
|
|
],
|
|
"CHANNEL_MODE",
|
|
)?;
|
|
ensure_member(
|
|
&input.intent,
|
|
&[
|
|
"IDENTIFY",
|
|
"ENTER_CHANNEL",
|
|
"CONVERSE",
|
|
"DECLARE",
|
|
"REQUEST_PLAN",
|
|
"REQUEST_BROADCAST",
|
|
"ACTIVATE_LOCAL_MODE",
|
|
"DRAFT_BROADCAST",
|
|
"RECEIVE_DOCUMENT",
|
|
"PUBLISH_EXTERNAL",
|
|
"QUERY_STATUS",
|
|
"PROPOSE_HANDOFF",
|
|
"ACCEPT_HANDOFF",
|
|
"REQUEST_REALITY_ACTION",
|
|
"REPORT_RESULT",
|
|
"CORRECT",
|
|
"END_INTERACTION",
|
|
"EXIT_CHANNEL",
|
|
"SEAL_LANGUAGE_RECORD",
|
|
"ORDINARY_DIALOGUE",
|
|
],
|
|
"INTENT",
|
|
)?;
|
|
for evidence in &input.evidence {
|
|
if evidence.r#type.trim().is_empty() || evidence.r#ref.trim().is_empty() {
|
|
return Err("HOLOLAKE_CHANNEL_RECEIPT_EVIDENCE_INVALID".into());
|
|
}
|
|
}
|
|
if input
|
|
.required_proof
|
|
.iter()
|
|
.any(|proof| proof.trim().is_empty())
|
|
{
|
|
return Err("HOLOLAKE_CHANNEL_RECEIPT_REQUIRED_PROOF_INVALID".into());
|
|
}
|
|
let required_proof = input
|
|
.required_proof
|
|
.iter()
|
|
.cloned()
|
|
.collect::<BTreeSet<_>>()
|
|
.into_iter()
|
|
.collect::<Vec<_>>();
|
|
let declared = input
|
|
.evidence
|
|
.iter()
|
|
.filter(|item| item.r#type == "EXECUTION_RECEIPT" && item.external && item.verified)
|
|
.flat_map(|item| item.proves.iter().cloned())
|
|
.collect::<HashSet<_>>();
|
|
let has_external_receipt = input
|
|
.evidence
|
|
.iter()
|
|
.any(|item| item.r#type == "EXECUTION_RECEIPT" && item.external && item.verified)
|
|
&& required_proof.iter().all(|proof| declared.contains(proof));
|
|
let authorized = input.authorization.as_ref().is_some_and(|authorization| {
|
|
authorization.current
|
|
&& authorization.scoped
|
|
&& authorization.unexpired
|
|
&& !authorization.r#ref.trim().is_empty()
|
|
});
|
|
let before = input.current_states.as_ref().map_or_else(
|
|
|| json!({"session":"DISCONNECTED","broadcast":"CLOSED","handoff":"NONE"}),
|
|
|states| json!({"session":states.session,"broadcast":states.broadcast,"handoff":states.handoff}),
|
|
);
|
|
ensure_member(
|
|
before["session"].as_str().unwrap_or(""),
|
|
&[
|
|
"DISCONNECTED",
|
|
"IDENTIFIED",
|
|
"CHANNEL_ACTIVE",
|
|
"STANDBY",
|
|
"CLOSED",
|
|
],
|
|
"SESSION_STATE",
|
|
)?;
|
|
ensure_member(
|
|
before["broadcast"].as_str().unwrap_or(""),
|
|
&[
|
|
"CLOSED",
|
|
"ARMED",
|
|
"DRAFTED",
|
|
"HUMAN_CONFIRMED",
|
|
"RECEIVED_LOCAL",
|
|
"EXTERNAL_IN_PROGRESS",
|
|
"EXTERNAL_VERIFIED",
|
|
],
|
|
"BROADCAST_STATE",
|
|
)?;
|
|
ensure_member(
|
|
before["handoff"].as_str().unwrap_or(""),
|
|
&["NONE", "PROPOSED", "TARGET_ACCEPTED", "ACTIVE", "REVOKED"],
|
|
"HANDOFF_STATE",
|
|
)?;
|
|
let mut after = before.clone();
|
|
let mut correction = "CLEAN";
|
|
let mut effect = "LANGUAGE_STATE_ONLY";
|
|
let mut reality_status = "NOT_APPLICABLE";
|
|
let mut next_step = "CONTINUE_IN_CHANNEL";
|
|
let mut boundaries = BTreeSet::new();
|
|
let reality_claim = input.claim_layer == "REALITY_CLAIM";
|
|
let simulation = input.claim_layer == "LANGUAGE_SIMULATION";
|
|
let conversation_only = input.channel_mode == "CONVERSATION_ONLY";
|
|
|
|
if matches!(
|
|
input.intent.as_str(),
|
|
"IDENTIFY"
|
|
| "ENTER_CHANNEL"
|
|
| "CONVERSE"
|
|
| "ORDINARY_DIALOGUE"
|
|
| "END_INTERACTION"
|
|
| "EXIT_CHANNEL"
|
|
) {
|
|
effect = "NO_EXTERNAL_EFFECT";
|
|
}
|
|
if input.intent == "IDENTIFY" {
|
|
after["session"] = json!("IDENTIFIED");
|
|
}
|
|
if input.intent == "ENTER_CHANNEL" {
|
|
after["session"] = json!("CHANNEL_ACTIVE");
|
|
}
|
|
if matches!(input.intent.as_str(), "END_INTERACTION" | "EXIT_CHANNEL") {
|
|
after["session"] = json!("CLOSED");
|
|
next_step = "STOP_OUTPUT_AFTER_MINIMAL_CLOSE_RECEIPT";
|
|
boundaries.insert("NO_ROLEPLAY_EPILOGUE_AFTER_CLOSE");
|
|
}
|
|
if before["session"] == "CLOSED"
|
|
&& !matches!(input.intent.as_str(), "IDENTIFY" | "ENTER_CHANNEL")
|
|
{
|
|
effect = "NO_EXTERNAL_EFFECT";
|
|
reality_status = "REJECTED";
|
|
next_step = "REQUIRE_NEW_HUMAN_DIRECT_CHANNEL_ENTRY";
|
|
boundaries.insert("CLOSED_SESSION_CANNOT_REACTIVATE_ITSELF");
|
|
}
|
|
if input.intent == "REQUEST_PLAN" || input.claim_layer == "ENGINEERING_PROPOSAL" {
|
|
effect = "PLAN_ONLY";
|
|
reality_status = "PROPOSED";
|
|
next_step = "REVIEW_PLAN";
|
|
}
|
|
match input.intent.as_str() {
|
|
"ACTIVATE_LOCAL_MODE" => {
|
|
after["broadcast"] = json!("ARMED");
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
next_step = "WAIT_FOR_DOCUMENT_OR_DRAFT_REQUEST";
|
|
}
|
|
"DRAFT_BROADCAST" => {
|
|
after["broadcast"] = json!("DRAFTED");
|
|
effect = "PLAN_ONLY";
|
|
next_step = "HUMAN_REVIEW_DRAFT";
|
|
}
|
|
"RECEIVE_DOCUMENT" => {
|
|
after["broadcast"] = json!("RECEIVED_LOCAL");
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
next_step = "RECORD_LOCAL_RECEIPT_ONLY";
|
|
boundaries.insert("RECEIVED_LOCAL_IS_NOT_EXTERNAL_PUBLISH");
|
|
}
|
|
_ => {}
|
|
}
|
|
if simulation {
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
reality_status = "NOT_APPLICABLE";
|
|
boundaries.insert("LANGUAGE_SIMULATION_ONLY");
|
|
}
|
|
if reality_claim {
|
|
reality_status = if has_external_receipt {
|
|
"VERIFIED"
|
|
} else {
|
|
"UNVERIFIED"
|
|
};
|
|
effect = if has_external_receipt {
|
|
"RESULT_RECORDED"
|
|
} else {
|
|
"NO_EXTERNAL_EFFECT"
|
|
};
|
|
next_step = if has_external_receipt {
|
|
"READ_BACK_EXTERNAL_RESULT"
|
|
} else {
|
|
"PROVIDE_EXTERNAL_EVIDENCE"
|
|
};
|
|
}
|
|
if input.intent == "REQUEST_REALITY_ACTION" {
|
|
if conversation_only {
|
|
effect = "NO_EXTERNAL_EFFECT";
|
|
reality_status = "REJECTED";
|
|
next_step = "MOVE_TO_AUTHORIZED_EXECUTION_CHANNEL";
|
|
boundaries.insert("CONVERSATION_CHANNEL_CANNOT_EXECUTE");
|
|
} else if !authorized {
|
|
effect = "PENDING_AUTHORIZATION";
|
|
reality_status = "PENDING_AUTHORIZATION";
|
|
next_step = "OBTAIN_CURRENT_SCOPED_AUTHORIZATION";
|
|
} else {
|
|
effect = "EXECUTION_ELIGIBLE";
|
|
reality_status = if has_external_receipt {
|
|
"VERIFIED"
|
|
} else {
|
|
"IN_PROGRESS_WITH_RECEIPT"
|
|
};
|
|
next_step = if has_external_receipt {
|
|
"READ_BACK_EXTERNAL_RESULT"
|
|
} else {
|
|
"EXECUTE_THROUGH_AUTHORIZED_ADAPTER"
|
|
};
|
|
}
|
|
}
|
|
if input.intent == "PUBLISH_EXTERNAL" {
|
|
if !authorized {
|
|
effect = "PENDING_AUTHORIZATION";
|
|
reality_status = "PENDING_AUTHORIZATION";
|
|
next_step = "OBTAIN_CURRENT_SCOPED_PUBLISH_AUTHORIZATION";
|
|
} else if has_external_receipt {
|
|
effect = "RESULT_RECORDED";
|
|
reality_status = "VERIFIED";
|
|
after["broadcast"] = json!("EXTERNAL_VERIFIED");
|
|
next_step = "READ_BACK_EXTERNAL_PUBLICATION";
|
|
} else {
|
|
effect = "EXECUTION_ELIGIBLE";
|
|
reality_status = "IN_PROGRESS_WITH_RECEIPT";
|
|
after["broadcast"] = json!("EXTERNAL_IN_PROGRESS");
|
|
next_step = "PUBLISH_THROUGH_AUTHORIZED_ADAPTER_AND_CAPTURE_READBACK";
|
|
}
|
|
}
|
|
if input.intent == "REQUEST_BROADCAST" {
|
|
if conversation_only || !authorized {
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
reality_status = if reality_claim {
|
|
"UNVERIFIED"
|
|
} else {
|
|
"NOT_APPLICABLE"
|
|
};
|
|
next_step = "OBTAIN_EXPLICIT_BROADCAST_AUTHORIZATION";
|
|
boundaries.insert("DRAFT_OR_LANGUAGE_BROADCAST_ONLY");
|
|
} else {
|
|
effect = "EXECUTION_ELIGIBLE";
|
|
reality_status = if has_external_receipt {
|
|
"VERIFIED"
|
|
} else {
|
|
"IN_PROGRESS_WITH_RECEIPT"
|
|
};
|
|
next_step = if has_external_receipt {
|
|
"READ_BACK_EXTERNAL_RESULT"
|
|
} else {
|
|
"SEND_THROUGH_AUTHORIZED_BROADCAST_ADAPTER"
|
|
};
|
|
}
|
|
}
|
|
if input.intent == "CORRECT" {
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
reality_status = "NOT_APPLICABLE";
|
|
next_step = "CREATE_CORRECTION_CANDIDATE_AND_RETEST";
|
|
correction = if input.prior_receipt_id.is_some() {
|
|
"SUPERSEDED"
|
|
} else {
|
|
"CORRECTION_PENDING"
|
|
};
|
|
}
|
|
if input.intent == "QUERY_STATUS" {
|
|
effect = if has_external_receipt {
|
|
"RESULT_RECORDED"
|
|
} else {
|
|
"NO_EXTERNAL_EFFECT"
|
|
};
|
|
reality_status = if has_external_receipt {
|
|
"VERIFIED"
|
|
} else {
|
|
"UNVERIFIED"
|
|
};
|
|
next_step = if has_external_receipt {
|
|
"REPORT_OBSERVED_STATUS_WITH_SCOPE"
|
|
} else {
|
|
"REPORT_NO_OBSERVATION_SOURCE"
|
|
};
|
|
if !has_external_receipt {
|
|
boundaries.insert("DO_NOT_GUESS_STATUS_WITHOUT_OBSERVATION");
|
|
}
|
|
}
|
|
if input.intent == "PROPOSE_HANDOFF" {
|
|
after["handoff"] = json!("PROPOSED");
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
reality_status = "PROPOSED";
|
|
next_step = "WAIT_FOR_INDEPENDENT_TARGET_ACCEPTANCE";
|
|
boundaries.insert("PROPOSAL_IS_NOT_ACTIVE_HANDOFF");
|
|
}
|
|
if input.intent == "ACCEPT_HANDOFF" {
|
|
let accepted = input.handoff.as_ref().is_some_and(|handoff| {
|
|
handoff.target_acceptance && handoff.target_id == input.actor_id
|
|
});
|
|
if before["handoff"] != "PROPOSED" || !accepted {
|
|
effect = "NO_EXTERNAL_EFFECT";
|
|
reality_status = "REJECTED";
|
|
next_step = "OBTAIN_INDEPENDENT_ACCEPTANCE_FROM_TARGET";
|
|
boundaries.insert("MODEL_CANNOT_ACCEPT_FOR_TARGET");
|
|
} else {
|
|
after["handoff"] = json!("TARGET_ACCEPTED");
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
reality_status = "PROPOSED";
|
|
next_step = "APPLY_SCOPED_HANDOFF_AND_CAPTURE_READBACK";
|
|
}
|
|
}
|
|
if input.source_layer == "MODEL_RESPONSE" {
|
|
boundaries.insert("MODEL_RESPONSE_IS_NOT_EXTERNAL_EVIDENCE");
|
|
}
|
|
if input.intent == "IDENTIFY" {
|
|
boundaries.insert("IDENTIFICATION_IS_NOT_BROADCAST");
|
|
}
|
|
if input.intent == "ENTER_CHANNEL" {
|
|
boundaries.insert("CHANNEL_ENTRY_IS_NOT_PERSONA_OR_AUTHORITY_TRANSFER");
|
|
}
|
|
if !required_proof.is_empty() && !has_external_receipt {
|
|
boundaries.insert("EVIDENCE_SCOPE_DOES_NOT_PROVE_REQUESTED_EFFECT");
|
|
}
|
|
if !has_external_receipt && (reality_status == "VERIFIED" || effect == "RESULT_RECORDED") {
|
|
return Err("HOLOLAKE_CHANNEL_RECEIPT_EXTERNAL_EVIDENCE_REQUIRED".into());
|
|
}
|
|
|
|
let boundaries = boundaries
|
|
.into_iter()
|
|
.map(str::to_string)
|
|
.collect::<Vec<_>>();
|
|
let supersedes = if correction == "SUPERSEDED" {
|
|
input.prior_receipt_id.clone().into_iter().collect()
|
|
} else {
|
|
Vec::new()
|
|
};
|
|
let base = json!({
|
|
"schema": SCHEMA, "contractId": CONTRACT_ID, "eventId": input.event_id,
|
|
"received": true, "identified": if input.intent == "IDENTIFY" { Some(input.actor_id.clone()) } else { None },
|
|
"channel": {"id":input.channel_id,"mode":input.channel_mode}, "intent":input.intent,
|
|
"claim":{"layer":input.claim_layer,"sourceLayer":input.source_layer},
|
|
"affectedLayer":if reality_claim { "REALITY_EVIDENCE_LAYER" } else { "LANGUAGE_LAYER" },
|
|
"effect":effect,"realityStatus":reality_status,"evidence":input.evidence,
|
|
"requiredProof":required_proof,"states":{"before":before,"after":after,"correction":correction},
|
|
"supersedes":supersedes,"boundaries":boundaries,"nextStep":next_step
|
|
});
|
|
let receipt_id = format!(
|
|
"GH-CR-{}",
|
|
&sha256(&serde_json::to_vec(&base).unwrap_or_default())[..20]
|
|
);
|
|
Ok(ChannelReceipt {
|
|
schema: SCHEMA,
|
|
contract_id: CONTRACT_ID,
|
|
receipt_id,
|
|
event_id: base["eventId"].as_str().unwrap_or_default().into(),
|
|
received: true,
|
|
identified: base["identified"].as_str().map(str::to_string),
|
|
channel: base["channel"].clone(),
|
|
intent: base["intent"].as_str().unwrap_or_default().into(),
|
|
claim: base["claim"].clone(),
|
|
affected_layer: base["affectedLayer"].as_str().unwrap_or_default().into(),
|
|
effect: effect.into(),
|
|
reality_status: reality_status.into(),
|
|
evidence: input.evidence,
|
|
required_proof,
|
|
states: base["states"].clone(),
|
|
supersedes,
|
|
boundaries,
|
|
next_step: next_step.into(),
|
|
previous_ledger_hash: "GENESIS".into(),
|
|
ledger_receipt_hash: String::new(),
|
|
})
|
|
}
|
|
|
|
fn ensure_member(value: &str, allowed: &[&str], label: &str) -> Result<(), String> {
|
|
if allowed.contains(&value) {
|
|
Ok(())
|
|
} else {
|
|
Err(format!("HOLOLAKE_CHANNEL_RECEIPT_{label}_UNSUPPORTED"))
|
|
}
|
|
}
|
|
|
|
fn ledger_path(app: &AppHandle) -> Result<PathBuf, String> {
|
|
Ok(
|
|
crate::authenticated_storage::account_storage_root(app, "channel-receipts-v1")?
|
|
.join("receipts.jsonl"),
|
|
)
|
|
}
|
|
|
|
fn last_hash(path: &PathBuf) -> Result<String, String> {
|
|
if !path.exists() {
|
|
return Ok("GENESIS".into());
|
|
}
|
|
let body = fs::read_to_string(path)
|
|
.map_err(|error| format!("HOLOLAKE_CHANNEL_RECEIPT_LEDGER_READ_FAILED: {error}"))?;
|
|
Ok(body
|
|
.lines()
|
|
.last()
|
|
.and_then(|line| serde_json::from_str::<Value>(line).ok())
|
|
.and_then(|value| {
|
|
value
|
|
.get("ledgerReceiptHash")
|
|
.and_then(Value::as_str)
|
|
.map(str::to_string)
|
|
})
|
|
.unwrap_or_else(|| "GENESIS".into()))
|
|
}
|
|
|
|
fn append(path: &PathBuf, receipt: &ChannelReceipt) -> Result<(), String> {
|
|
if let Some(parent) = path.parent() {
|
|
fs::create_dir_all(parent)
|
|
.map_err(|error| format!("HOLOLAKE_CHANNEL_RECEIPT_LEDGER_WRITE_FAILED: {error}"))?;
|
|
}
|
|
let mut file = fs::OpenOptions::new()
|
|
.create(true)
|
|
.append(true)
|
|
.open(path)
|
|
.map_err(|error| format!("HOLOLAKE_CHANNEL_RECEIPT_LEDGER_WRITE_FAILED: {error}"))?;
|
|
writeln!(
|
|
file,
|
|
"{}",
|
|
serde_json::to_string(receipt)
|
|
.map_err(|error| format!("HOLOLAKE_CHANNEL_RECEIPT_INVALID: {error}"))?
|
|
)
|
|
.map_err(|error| format!("HOLOLAKE_CHANNEL_RECEIPT_LEDGER_WRITE_FAILED: {error}"))
|
|
}
|
|
|
|
fn sha256(bytes: &[u8]) -> String {
|
|
digest(&SHA256, bytes)
|
|
.as_ref()
|
|
.iter()
|
|
.map(|byte| format!("{byte:02x}"))
|
|
.collect()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
fn input(intent: &str, claim_layer: &str) -> CompileChannelReceiptInput {
|
|
CompileChannelReceiptInput {
|
|
event_id: "E-1".into(),
|
|
channel_id: "ICE-CH-ZC001".into(),
|
|
channel_mode: "REALITY_EXECUTION".into(),
|
|
source_layer: "MODEL_RESPONSE".into(),
|
|
actor_id: "carrier".into(),
|
|
intent: intent.into(),
|
|
claim_layer: claim_layer.into(),
|
|
required_proof: vec![],
|
|
evidence: vec![],
|
|
authorization: None,
|
|
current_states: None,
|
|
prior_receipt_id: None,
|
|
handoff: None,
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn model_reality_claim_stays_unverified_without_external_receipt() {
|
|
let receipt = compile_pure(input("REPORT_RESULT", "REALITY_CLAIM")).unwrap();
|
|
assert_eq!(receipt.reality_status, "UNVERIFIED");
|
|
assert_eq!(receipt.effect, "NO_EXTERNAL_EFFECT");
|
|
assert!(receipt
|
|
.boundaries
|
|
.contains(&"MODEL_RESPONSE_IS_NOT_EXTERNAL_EVIDENCE".into()));
|
|
}
|
|
|
|
#[test]
|
|
fn reality_action_requires_current_scoped_authorization() {
|
|
let receipt = compile_pure(input("REQUEST_REALITY_ACTION", "REALITY_CLAIM")).unwrap();
|
|
assert_eq!(receipt.reality_status, "PENDING_AUTHORIZATION");
|
|
assert_eq!(receipt.effect, "PENDING_AUTHORIZATION");
|
|
}
|
|
|
|
#[test]
|
|
fn verified_status_requires_proof_scoped_external_receipt() {
|
|
let mut value = input("QUERY_STATUS", "REALITY_CLAIM");
|
|
value.required_proof = vec!["target-a".into()];
|
|
value.evidence.push(ChannelEvidence {
|
|
r#type: "EXECUTION_RECEIPT".into(),
|
|
r#ref: "receipt://1".into(),
|
|
verified: true,
|
|
external: true,
|
|
proves: vec!["target-a".into()],
|
|
does_not_prove: vec!["target-b".into()],
|
|
});
|
|
let receipt = compile_pure(value).unwrap();
|
|
assert_eq!(receipt.reality_status, "VERIFIED");
|
|
assert_eq!(receipt.effect, "RESULT_RECORDED");
|
|
}
|
|
}
|