Guarantee non-empty xml_schema: <feedback> identifies the report, not <version>

The <feedback> XML root element (anchored at the top of
parse_aggregate_report_xml) is what identifies an aggregate report;
<version> is optional metadata per RFC 7489 Appendix C. The "draft"
fallback only covered a fully absent <version>: an empty <version/>
(which xmltodict parses as None) or a whitespace-only value produced
xml_schema=None, which the flat-row serializer coerced to "" — and any
consumer detecting aggregate rows by a non-empty xml_schema, such as
the Google SecOps CBN parser's report-type cascade, silently dropped
the row. The fallback now applies unless <version> carries non-empty
text (attribute-wrapped values are unwrapped via _text like other
elements).

The regression test fails on the previous code with
xml_schema=None != "draft".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Sean Whalen
2026-07-11 15:52:47 -04:00
co-authored by Claude Fable 5
parent a131fa937b
commit 571bbf741b
5 changed files with 94 additions and 5 deletions
+4 -1
View File
@@ -57,7 +57,10 @@ The `or` fallbacks matter: text-format failure reports have no `Feedback-Type`
field (parsedmarc emits no `feedback_type` key for them, but always computes
`arrival_date_utc`), and SMTP TLS failure-detail rows from parsedmarc versions
older than this parser lack `policy_type` (every RFC 8460 failure detail has a
`result_type`).
`result_type`). `xml_schema` needs no fallback: the `<feedback>` XML root
element is what identifies an aggregate report, and parsedmarc guarantees a
non-empty `xml_schema` on every aggregate row ("draft" whenever `<version>`
is missing, empty, or whitespace).
`EMAIL_TRANSACTION` and `GENERIC_EVENT` are both valid `metadata.event_type`
values. Note that **`GENERIC_EVENT` events only appear in raw-log and UDM