{
"schema_version": 1,
"evidence": {
"asn1-signatures": {
"positive": [{"file":"tests/xmlsec1_interop.rs","test":"asn1_ecdsa_compatibility_matches_pinned_xmlsec1","description":"Pinned donor and native verification accept the upstream DER fixture only in explicit compatibility mode."},{"file":"tests/signing_digest.rs","test":"ecdsa_asn1_compatibility_is_explicit_across_the_signing_pipeline","description":"Native signing emits ASN.1 DER only under explicit policy and verifies the result under the matching policy."},{"file":"tools/xmlsec1/tests/process_contract.rs","test":"cli_asn1_signature_mode_requires_the_explicit_donor_flag","description":"The native CLI flag controls both ASN.1 signing output and verification acceptance."}],
"negative": [{"file":"tests/xmlsec1_interop.rs","test":"asn1_ecdsa_compatibility_matches_pinned_xmlsec1","description":"Pinned donor and native standards defaults both reject the upstream DER fixture."},{"file":"tests/signing_digest.rs","test":"ecdsa_asn1_compatibility_is_explicit_across_the_signing_pipeline","description":"Standards-default native verification rejects DER emitted by compatibility-mode signing."},{"file":"tools/xmlsec1/tests/process_contract.rs","test":"cli_asn1_signature_mode_requires_the_explicit_donor_flag","description":"CLI verification without the compatibility flag rejects ASN.1 DER SignatureValue framing."}]
},
"c-boundary-state": {
"positive": [{"file":"tests/behavioral_compatibility.rs","test":"pinned_c_oracle_reports_context_callback_and_dom_contracts","description":"A compiled probe measures successful and invalid context state, retained references, pre-execution callback order, userData propagation, and in-place signing mutation against pinned libxmlsec1."},{"file":"tests/behavioral_compatibility.rs","test":"c_boundary_behaviors_are_explicitly_planned","description":"Measured donor-only context, callback, and in-place mutation contracts are named compatibility work."}],
"negative": [{"file":"tests/behavioral_compatibility.rs","test":"pinned_c_oracle_reports_context_callback_and_dom_contracts","description":"The probe measures callback-abort error state and its retained failed reference, distinguishing processing errors from invalid results."},{"file":"tests/behavioral_compatibility.rs","test":"c_boundary_behaviors_are_not_claimed_as_native","description":"The ledger prevents native Rust APIs from implying C object-state parity."}]
},
"error-invalid": {
"positive": [{"file":"tests/signature_pipeline_integration.rs","test":"tampered_signature_value_fails_after_references_pass","description":"Cryptographic mismatch returns an invalid verification result."}],
"negative": [{"file":"tests/signature_pipeline_integration.rs","test":"malformed_signature_value_base64_returns_decode_error","description":"Malformed wire syntax remains a processing error."},{"file":"tests/donor_negative_vectors.rs","test":"phaos_bad_signature_artifact_fails_on_its_unsupported_md5_reference","description":"An unsupported Reference digest algorithm remains a typed processing error rather than an invalid verification result."}]
},
"here-semantics": {
"positive": [{"file":"tests/xpath_transform_integration.rs","test":"here_semantics_are_explicit_across_signing_and_verification","description":"Both standards and libxmlsec1 here() bindings round-trip when selected explicitly."}],
"negative": [{"file":"tests/base64_transform_integration.rs","test":"decoded_xml_rejects_here_from_the_signature_document","description":"here() provenance cannot cross a binary-to-XML document boundary."}]
},
"id-resolution": {
"positive": [{"file":"tools/xmlsec1/tests/process_contract.rs","test":"scoped_id_attribute_selects_and_signs_the_registered_element","description":"Caller-registered ID attributes reach signing selection and dereference."},{"file":"tests/signing_digest.rs","test":"signing_internal_dtd_policy_reaches_builder_and_mutation_reparses","description":"Explicit internal-DTD policy reaches the complete signing pipeline."},{"file":"src/xml.rs","test":"dtd_id_declarations_do_not_replace_request_registration","description":"Caller registration indexes a custom attribute even when its ID type is also declared in an allowed internal DTD."}],
"negative": [{"file":"tests/merlin_interop.rs","test":"rejects_dtd_and_unsupported_retrieval_defaults","description":"DTD parsing and unsupported retrieval remain disabled by default."},{"file":"src/xml.rs","test":"dtd_id_declarations_do_not_replace_request_registration","description":"Allowing an internal DTD does not implicitly register its custom ID-typed attributes in the owned Rust tree."}]
},
"manifest-status": {
"positive": [{"file":"tests/signing_digest.rs","test":"sign_context_processes_manifests_before_signed_info","description":"Authenticated Manifest references are processed before SignedInfo signing."}],
"negative": [{"file":"tests/signing_digest.rs","test":"manifest_signing_rejects_digest_dependency_cycles","description":"Cyclic Manifest dependencies fail closed."}]
},
"multiple-signatures": {
"positive": [{"file":"tests/signing_digest.rs","test":"sign_context_targets_the_last_signature_template_by_default","description":"Signing has an explicit deterministic target among multiple templates."}],
"negative": [{"file":"tests/signature_pipeline_integration.rs","test":"multiple_signature_elements_are_rejected","description":"Verification default rejects ambiguous multiple signatures."}]
},
"transform-adapters": {
"positive": [{"file":"tests/signing_digest.rs","test":"signing_policy_covers_implicit_and_signed_info_canonicalization","description":"Implicit C14N participates in the operation policy and budgets."}],
"negative": [{"file":"tests/base64_transform_integration.rs","test":"binary_to_node_set_adapter_rejects_malformed_xml","description":"The octet-to-XML adapter rejects malformed XML rather than coercing it."}]
},
"uri-identity": {
"positive": [{"file":"tests/uri_integration.rs","test":"xpointer_id_canonicalizes_same_as_bare_name","description":"Bare ID and xpointer(id()) select the same subtree."}],
"negative": [{"file":"tests/uri_integration.rs","test":"xpointer_root_vs_empty_uri_comment_difference","description":"Empty URI and xpointer(/) preserve their normative comment difference."}]
},
"visa3d-ids": {
"positive": [{"file":"tests/xmlsec1_interop.rs","test":"visa3d_direct_id_compatibility_matches_pinned_xmlsec1","description":"Pinned donor and native compatibility mode resolve an ID that cannot be embedded in the default XPointer wrapper."}],
"negative": [{"file":"src/xmldsig/uri.rs","test":"bare_fragment_rejects_non_ncname_without_visa3d_compatibility","description":"Standards-default resolution rejects a non-NCName bare fragment."}]
}
},
"behaviors": [
{"id":"behavior-001","category":"here-semantics","summary":"XPath here() has explicit standards and libxmlsec1 node bindings.","classification":"compatibility-policy","control":{"boundary":"typed operation policy","setting":"TransformPolicy.xpath_here_semantics","default":"XMLDSig specification binding"},"evidence":"here-semantics","donor_anchors":[{"source":"src/xpath.c","needle":"xmlSecTransformXPathNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx)"},{"source":"src/xpath.c","needle":"xmlXPathRegisterFunc(data->ctx, (xmlChar *)\"here\", xmlSecXPathHereFunction);"}]},
{"id":"behavior-002","category":"visa3d-ids","summary":"Visa3D mode resolves registered bare-fragment IDs directly instead of constructing an XPointer expression.","classification":"compatibility-policy","control":{"boundary":"typed operation policy and native CLI flag","setting":"TransformPolicy.same_document_id_semantics / --enable-visa3d-hack","default":"library API uses XMLDSig grammar; native CLI uses libxmlsec1 wrapped-barename grammar with comments excluded"},"evidence":"visa3d-ids","donor_anchors":[{"source":"apps/xmlsec.c","needle":"\"--enable-visa3d-hack\","},{"source":"src/xmldsig.c","needle":"XMLSEC_DSIG_FLAGS_USE_VISA3D_HACK"}]},
{"id":"behavior-003","category":"signature-value-encoding","summary":"ASN.1 DER ECDSA SignatureValue is an explicit libxmlsec1 compatibility wire format.","classification":"compatibility-policy","control":{"boundary":"typed signing/verification policy and native CLI flag","setting":"EcdsaSignatureValueEncoding / --enable-asn1-signatures-hack","default":"XMLDSig fixed-width r||s"},"evidence":"asn1-signatures","donor_anchors":[{"source":"apps/xmlsec.c","needle":"\"--enable-asn1-signatures-hack\","},{"source":"src/openssl/signatures.c","needle":"static int\nxmlSecOpenSSLEvpSignatureEcdsa_XmlDSig2OpenSSL("},{"source":"src/openssl/signatures.c","needle":"static int\nxmlSecOpenSSLEvpSignatureEcdsa_OpenSSL2XmlDSig("}]},
{"id":"behavior-004","category":"implicit-c14n-adapters","summary":"Transform chains insert XML/octet adapters and implicit inclusive C14N according to adjacent data types.","classification":"native","control":{"boundary":"typed transform policy and shared operation budgets","setting":"TransformPolicy.allowed_algorithms and ResourcePolicy","default":"implemented adapters enabled within limits"},"evidence":"transform-adapters","donor_anchors":[{"source":"src/transforms.c","needle":"middleId = xmlSecTransformXmlParserId;"},{"source":"src/transforms.c","needle":"middleId = xmlSecTransformInclC14NId;"}]},
{"id":"behavior-005","category":"empty-uri-xpointer","summary":"Empty URI excludes comments while xpointer(/) retains them; xpointer(id()) and bare IDs share target identity.","classification":"native","control":{"boundary":"typed URI policy","setting":"UriPolicy.references","default":"same-document references only"},"evidence":"uri-identity","donor_anchors":[{"source":"src/transforms.c","needle":"transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformXPointerId);"},{"source":"src/transforms.c","needle":"transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformVisa3DHackId);"}]},
{"id":"behavior-006","category":"dtd-xml-id-caller-id","summary":"Internal-DTD parsing and ID registration are separate controls; DTD declarations do not implicitly register custom ID attributes in the owned Rust tree.","classification":"native","control":{"boundary":"typed XML policy plus request-scoped ID registrations","setting":"XmlInputPolicy.allow_internal_dtd and VerifyContext/SignContext id_attributes","default":"DTD disabled; xml:id and built-in XMLDSig ID spellings indexed; custom attributes require caller registration"},"evidence":"id-resolution","donor_anchors":[{"source":"src/xmltree.c","needle":"xmlSecAddIDs(xmlDocPtr doc, xmlNodePtr node, const xmlChar** ids)"},{"source":"apps/xmlsec.c","needle":"xmlSecAddIDs(data->doc, NULL, idAttr);"}]},
{"id":"behavior-007","category":"multiple-signatures","summary":"Operations select one Signature deterministically and reject ambiguous verification by default.","classification":"native","control":{"boundary":"request-scoped operation selection","setting":"SignatureSelection and SignatureTemplateSelection","default":"unique verification signature; last signing template"},"evidence":"multiple-signatures","donor_anchors":[{"source":"src/xmldsig.c","needle":"xmlSecDSigCtxVerify(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node)"}]},
{"id":"behavior-008","category":"manifest-status","summary":"Manifest processing is explicit and reports authenticated nested reference results separately.","classification":"compatibility-policy","control":{"boundary":"typed operation policy","setting":"ManifestProcessing","default":"ignore Manifest references"},"evidence":"manifest-status","donor_anchors":[{"source":"src/xmldsig.c","needle":"dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginManifest);"},{"source":"src/xmldsig.c","needle":"if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS) == 0)"}]},
{"id":"behavior-009","category":"error-invalid-classification","summary":"Well-formed verification mismatches are invalid results; malformed or unsupported processing is an error.","classification":"native","control":{"boundary":"public verification result and typed error contract","setting":"DsigStatus / DsigError","default":"fail closed without coercing errors to invalid"},"evidence":"error-invalid","donor_anchors":[{"source":"src/xmldsig.c","needle":"dsigCtx->status = xmlSecDSigStatusInvalid;"},{"source":"src/xmldsig.c","needle":"xmlSecDSigCtxVerify(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node)"}]},
{"id":"behavior-010","category":"context-after-failure","summary":"Mutable xmlSecDSigCtx status, failure reason, and retained reference state after failure belong to the future C boundary.","classification":"planned-c-compatibility-boundary","control":{"boundary":"future C compatibility crate","setting":"C context lifecycle compatibility profile","default":"native Rust returns immutable results or typed errors"},"evidence":"c-boundary-state","donor_anchors":[{"source":"src/xmldsig.c","needle":"xmlSecDSigCtxMarkAsFailed(xmlSecDSigCtxPtr dsigCtx, xmlSecDSigFailureReason failureReason)"}]},
{"id":"behavior-011","category":"callback-ordering","summary":"Reference pre-execute callback ordering and userData propagation belong to the future C boundary.","classification":"planned-c-compatibility-boundary","control":{"boundary":"future C compatibility crate","setting":"C callback lifecycle compatibility profile","default":"native core exposes no global or implicit callbacks"},"evidence":"c-boundary-state","donor_anchors":[{"source":"src/xmldsig.c","needle":"dsigRefCtx->transformCtx.preExecCallback = dsigCtx->referencePreExecuteCallback;"},{"source":"src/xmldsig.c","needle":"dsigRefCtx->transformCtx.userData = dsigCtx->userData;"}]},
{"id":"behavior-012","category":"dom-mutation","summary":"libxmlsec1 mutates SignatureValue and DigestValue nodes in place; native Rust returns a new serialized document.","classification":"planned-c-compatibility-boundary","control":{"boundary":"future libxml2 C DOM adapter","setting":"C DOM mutation compatibility profile","default":"owned immutable Rust input with explicit returned output"},"evidence":"c-boundary-state","donor_anchors":[{"source":"src/xmldsig.c","needle":"xmlNodeSetContentLen(dsigCtx->signValueNode, outBuf, outLen);"},{"source":"src/xmldsig.c","needle":"xmlNodeSetContentLen(digestValueNode, outBuf, outLen);"}]}
]
}