Release note · August 6, 2026
A relationship match is not case-sensitive
A relationship selector's placement and attributes are syntax. Once that syntax is valid, the OPC Relationships Transform defines exactly which stored relationships the selector chooses. ECMA-376 Open Packaging Conventions §10.6 says that matching is ASCII case-insensitive. DocFence 0.59 now applies that rule in its bounded static coverage audit.
Selection is an algorithm, not a string lookup
Consider a stored relationship and a well-shaped selector:
<Relationship Id="rIdStyles"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"
Target="styles.xml"/>
<opc:RelationshipReference SourceId="RIDSTYLES"/>
Those two ID values differ only in ASCII letter case. The transform selects the relationship. The same rule applies to a RelationshipsGroupReference/@SourceType and a stored relationship Type. If several stored IDs differ only by ASCII case, every matching relationship is selected.
Earlier DocFence coverage resolution used exact string equality. A standards-shaped declaration with a case-only difference could therefore look unresolved or uncovered even though the OPC transform would select it. That is a correctness gap in an audit meant to state what stored declarations cover.
A deliberately narrow correction
0.59 folds only ASCII A–Z when comparing selector values with stored relationship IDs and types. It does not apply broad Unicode normalization, rewrite package content, widen the selector syntax accepted in 0.58, execute a transform, canonicalize XML, recompute a digest, verify XMLDSIG, or make a trust decision.
The global boundary remains strict: selectors must be direct, child-free children of a Relationship Transform with exactly their required attribute. The change occurs only after that syntax passes, when DocFence reports bounded declared package-signature coverage.
version: 1
rules:
require_complete_package_signature_coverage: true
no_package_signature_coverage_changes: true
Evidence and use
The 70-test suite now covers case-insensitive SourceId matching, case-insensitive SourceType matching, and a selector that must select multiple case-colliding IDs. Across the 29 DOCX fixtures in the public OOXML Signature Security artifacts, 21 XML signature parts parse successfully. Their 38 Relationship Transforms contain 106 direct selectors; none has a case-only stored match or a folded-ID collision, so their public profiles remain identical to 0.58.
Main and tagged CI passed. Two independent epoch-fixed builds were byte-identical; anonymous downloads of the published wheel and source distribution matched those artifacts byte-for-byte. SHA-256: wheel 94aca4b08950ba5f9e586c65424361620a654db53d87029522aa2b8ce787a625; source distribution 31ca90d4c5fb8131b1df0bb960d2ac78344667b923e9c0c402391aac4e5ccdee.
python -m pip install https://github.com/SybilGambleyyu/docfence/releases/download/v0.59.0/docfence-0.59.0-py3-none-any.whl
docfence check approved.docx candidate.docx --policy docfence.yml --format sarif --output docfence.sarif
The tagged policy reference, threat model, and validation notes describe the exact scope. A coverage statement should follow the transform it is describing—no more, and no less.