# OPC Relationship Transforms
The XMLDSig algorithm
`http://schemas.openxmlformats.org/package/2006/RelationshipTransform`
selects and normalizes relationships before canonicalization. It supports both
`RelationshipReference SourceId` and `RelationshipsGroupReference SourceType`,
including multiple relationships with the same Type. Selectors form a union.
## Trusted Edition Selection
The edition is an application decision, not a property inferred from XML:
```rust
use xml_sec::policy::{OpcRelationshipEdition, VerificationPolicy};
let mut policy = VerificationPolicy::default();
policy.transforms.opc_relationship_edition = OpcRelationshipEdition::Ecma2012;
```
Pass that policy to `VerifyContext::policy`; select the same edition in
`SigningPolicy` when signing. `DecryptionPolicy` uses the same typed field for
CipherReference transforms. Verification never retries another edition.
For standalone chains, pass the same `VerificationPolicy` snapshot to
`xmldsig::execute_transforms_with_policy`; it enforces transform permissions,
XML allowances and resource limits as well as the edition. `execute_transforms`
uses the default snapshot.
| ECMA-376 Part 2 (2012), §13.2.4.24 | Case-sensitive Unicode | Remove Relationship contents and container-edge characters; remove comments |
| ECMA-376 Part 2 (2021), §10.6, library default | ASCII case-insensitive | Remove text and comments; preserve processing instructions |
Both editions order Ids case-sensitively, reject duplicate identifiers, remove
namespace prefixes and unused namespace declarations, and insert an absent
`TargetMode="Internal"`. The CLI selects the 2012 compatibility contract.
## Building a Reference
```rust
use xml_sec::c14n::{C14nAlgorithm, C14nMode};
use xml_sec::xmldsig::{DigestAlgorithm, ReferenceBuilder, RelationshipSelector, Transform};
let reference = ReferenceBuilder::new(DigestAlgorithm::Sha256)
.uri("_rels/.rels")
.transform(Transform::Relationship(vec![
RelationshipSelector::SourceId("rId1".into()),
RelationshipSelector::SourceType("urn:example:relationships".into()),
]))
.transform(Transform::C14n(C14nAlgorithm::new(C14nMode::Inclusive1_0, false)));
```
Provide external part bytes through the operation's caller-owned resource map and
explicitly permit the URI class in policy. The core performs no filesystem or
network discovery. A canonicalization transform must immediately follow the
Relationship Transform; both editions require inclusive C14N 1.0 with or without
comments (2012 §13.2.4.4; 2021 §10.5.8.2).
The CLI accepts detached reference bytes through explicit mappings:
```sh
xmlsec1 sign --privkey-pem key.pem --url-map:part.rels part.rels --output signed.xml template.xml
xmlsec1 verify --pubkey-pem public.pem --url-map:part.rels part.rels signed.xml
```
The mapping matches the resolved reference URI exactly. Duplicate mappings and
missing URL parameters are rejected. Unmapped references never open files or
fetch URLs; per-file and aggregate operation limits bound mapped bytes.
MCE processing follows the selected edition, with only the Relationships
application namespace understood. Ignorable and ProcessContent bindings retain
their declaring namespace scope, AlternateContent selects the first understood
Choice or its Fallback. In the 2012 contract, a nested Ignorable declaration resets
inherited ProcessContent for its listed namespaces unless locally overridden
(Part 3:2012 §10.1.1). The 2021 contract uses Part 3:2015 §9.2 instead: matching
ProcessContent declarations on any ancestor remain effective.
The 2012 contract also requires ProcessContent namespaces to appear in Ignorable
on the same element (§10.1.2), and checks MustUnderstand before ignoring encountered
elements and on every Choice/Fallback (§§10.1.3, 10.2.1). The 2021 contract permits
inherited Ignorable for ProcessContent and checks MustUnderstand after ignore and
branch selection (Part 3:2015 §§7.3, 9.4). Contents of unselected branches are not
visited in either edition. MCE attributes on direct AlternateContent children are
validated before any ignore decision, just as on other encountered elements.
`mc:PreserveElements` and `mc:PreserveAttributes` are
unknown attributes in both supported vocabularies (Part 3:2012 §10;
Part 3:2015 §7), not silently ignored preservation requests.
Traversal is iterative and charged to operation limits.
`ResourcePolicy.max_opc_parameter_bytes` bounds cumulative parameter allocations;
`max_opc_workspace_bytes` bounds cumulative normalization workspace. Shared XML,
node-filter work, and canonical output limits also apply. Node-set input respects
its visibility mask; byte input uses the selected XML backend and shared decoder,
including UTF-16. Relationship parts permit only UTF-8 or UTF-16, with declaration
labels limited to `UTF-8` and `UTF-16`, and reject DTDs even when the operation's
generic XML policy permits them (Part 2:2012 §9.1.4; Part 2:2021 §6.2.5).
These restrictions do not narrow other transforms' encoding support.
This transform is not a complete OPC package validator: package
part existence, target resolution, and signature packaging rules remain separate.
Internal Target syntax must be a relative reference; network-path references
are permitted by RFC 3986 §4.2. Determining whether they resolve inside the
same package requires its base pack IRI (2021 §§6.5.2.2-3), which the normalizer
does not receive. Acceptance by this transform does not assert package membership.
External Target syntax is validated before selection as well: relative references
or absolute IRIs are permitted. The 2012 contract also permits format-defined
fragments on absolute targets (§9.3.2.2); the 2021 contract specifies absolute-IRI
without a fragment (§6.5.3.4; RFC 3987 §2.2). Relative references may retain fragments
in either edition. Validation never resolves or fetches the target.
Relationship simple content is removed in both editions; non-whitespace text
in the Relationships container and child elements in Relationship remain invalid.
Selector simple content is permitted and ignored; selection uses only SourceId
or SourceType (2012 D.3; 2021 C.2). Relationship Type must be a complete absolute IRI
(RFC 3987 §2.2), even when unselected; Unicode in its remainder and its lexical spelling
are preserved (2012 §§3, 9.3.2; 2021 §§3.2.8, 6.5.3.4).
Generic SignedInfo and CipherReference execution therefore remain available.
Successful XMLDSig verification is not OPC package conformance: the package
adapter must independently enforce Manifest placement and one Relationship
Transform per package part (2021 §10.5.8.2; 2012 §§13.2.4.7, 13.2.4.23).
The normative editions are available from [Ecma International](https://ecma-international.org/publications-and-standards/standards/ecma-376/).