Pure-BEAM baseline adapter for XML seam enforcement.
Phase 28 (D-04): a single hardened parser path. parse_safely/2 runs the
pre-parse byte guards (DOCTYPE / ENTITY / size) on the raw binary BEFORE any
parse (XXE-before-verify invariant, D-09), then routes the well-formed arm to
Relyra.Security.XML.SaxyTree and re-derives EVERY downstream protocol field
from the resulting parse tree in one pass — the regex extractors are retired so
no parser/canonicalization differential exists (D-04, threat T-28-11).
The flat parsed_doc key contract is preserved additively (D-08): every legacy
key downstream readers (Relyra.Security.Signature,
Relyra.Protocol.ValidationPipeline) consume is reproduced, and the parse tree
is attached as a NEW :parse_tree key. The selected handle binds the EXACT
tree node canonicalize/2 serializes (D-10, anti-XSW), and canonicalize/2
delegates to the Relyra.Security.XML.C14N exclusive-C14N engine on that node
while failing closed (:canonicalization_failed) for any non-bindable handle
(Pitfall 9, threat T-28-12).
Summary
Functions
Pre-parse a SAML metadata document and produce a metadata-root-shaped
parsed_doc for the signed-metadata trust path (SIGV-04, D-13).
Functions
@spec parse_metadata_root_safely( binary(), keyword() ) :: {:ok, map()} | {:error, Relyra.Error.t()}
Pre-parse a SAML metadata document and produce a metadata-root-shaped
parsed_doc for the signed-metadata trust path (SIGV-04, D-13).
This is the metadata sibling of parse_safely/2: it runs the SAME pre-parse
byte guards (DOCTYPE / ENTITY / size) on the raw binary BEFORE any parse
(XXE-before-verify, D-09), routes the well-formed arm to the SAME SaxyTree
parser (D-04, one trust path — no regex, no second parser), and emits the SAME
canonical signed-candidate shape signed_candidates/1 emits (carrying the
D-02 crypto inputs :signed_info_node / :digest_value_b64 /
:signature_value_b64 plus the bound :node), but rooted at the metadata
envelope (<EntityDescriptor> / <EntitiesDescriptor>) instead of an
<Assertion>.
Returns {:ok, parsed_doc} whose single :signed_candidates entry binds the
EXACT metadata-root tree node canonicalize/2 serializes (anti-XSW), plus
:signature_method / :digest_method (from the SignedInfo), :key_info_trust
and :duplicate_ids (tree-derived) so the shared do_verify/4 gates inherit
to the metadata path. Returns {:error, %Error{type: :missing_signature}} when
no signed <EntityDescriptor> / <EntitiesDescriptor> root is present (fail
closed), or the same byte-guard / :malformed_xml errors parse_safely/2
returns.