{"record":{"id":"12832165367865ec","repo":"zeroclaw-labs/zeroclaw","slug":"serialize-canonical-content","errorCode":null,"errorMessage":"serialize canonical content","messagePattern":"serialize canonical content","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/zeroclaw-runtime/src/security/audit.rs","lineNumber":195,"sourceCode":"    pub fn with_security(mut self, sandbox_backend: Option<String>) -> Self {\n        self.security.sandbox_backend = sandbox_backend;\n        self\n    }\n}\n\nfn compute_entry_hash(prev_hash: &str, event: &AuditEvent) -> String {\n    // Build a canonical representation of the content fields only.\n    let content = serde_json::json!({\n        \"timestamp\": event.timestamp,\n        \"event_id\": event.event_id,\n        \"event_type\": event.event_type,\n        \"actor\": event.actor,\n        \"action\": event.action,\n        \"result\": event.result,\n        \"security\": event.security,\n        \"sequence\": event.sequence,\n    });\n    let content_json = serde_json::to_string(&content).expect(\"serialize canonical content\");\n\n    let mut hasher = Sha256::new();\n    hasher.update(prev_hash.as_bytes());\n    hasher.update(content_json.as_bytes());\n    hex::encode(hasher.finalize())\n}\n\n/// Internal chain state tracked across writes.\nstruct ChainState {\n    prev_hash: String,\n    sequence: u64,\n}\n\n/// Audit logger\npub struct AuditLogger {\n    log_path: PathBuf,\n    config: AuditConfig,\n    chain: Mutex<ChainState>,","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/security/audit.rs#L177-L213","documentation":"compute_entry_hash() serializes a JSON object built with json! from actor/action/result/security strings and a numeric sequence, then hashes the serialized bytes for the append-only audit hash chain. serde_json::to_string on such a value is infallible (no unserializable types, no streaming IO), so this expect documents an invariant rather than a recoverable error path.","triggerScenarios":"Any audit log() or verify_chain() call goes through this code; the panic would require serde to fail on plain strings and integers, which cannot happen. Not triggerable via audit event content.","commonSituations":"None for users. Maintainers extending the audit event schema with non-serializable custom types would need to revisit this expect.","solutions":["If extending the audit entry schema, keep fields to JSON-native types or propagate serialization as a Result.","No action needed for runtime users; verify_chain failures about hash mismatches are unrelated to this expect.","Run the audit log/verify_chain tests after schema changes."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep audit event fields to JSON-native types (strings, numbers) so serialization stays infallible.","If extending the schema with custom types, propagate to_string errors as Result instead of expect.","Distinguish hash-mismatch failures in verify_chain from this (unreachable) serialization expect."],"tags":["rust","serde","audit-log","hash-chain","invariant"],"backgroundTag":"serde-serialization-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}