natsmsg: mark the origin block recorded, so an absent field is an answer
Commit

Write-once had a blind spot: it decided "already recorded" field by field, from whether each header looked empty. Two origin fields are legitimately absent, so that read was wrong in the direction that corrupts.
A message captured OUTSIDE a JetStream domain has no origin domain to record, and one captured with no metadata at all has no origin stream, sequence or store time either. Reading those absences as "not yet recorded" let a LATER hop answer for the first one — writing its own domain, or the DLQ stream it read the record from, as where the message came from. Provenance that is silently wrong, which is worse than provenance that is missing, and the same class of defect as the overwrite this rule was added to prevent.
The origin block is now written once, as a block, gated on an explicit Nats-Dlq-Origin-Recorded marker. When it is present every origin field is carried through as-is and none is derived, absences included: an absent field means the hop that recorded the origin had nothing to record for it, and no later hop is entitled to a better answer. Per-hop fields are unchanged — always this capture's own.
Measuring the cross-domain case turned up why an origin domain is usually absent, and it is not what the field's name suggests. The domain reaches a client only as a token of the $JS.ACK reply subject, and on 2.14.3 the server emits the domain-bearing V2 form only behind the js_ack_fc_v2 feature flag, which is OFF by default. So a deployment can run with JetStreamDomain set and still hand every consumer a domainless MsgMetadata.Domain — an absent Nats-Dlq-Origin-Domain is the NORMAL case, and turning that flag on later must not make a later hop start claiming its domain as an older record's origin. Both facts are now measured (TestMsgMetadataDomainNeedsTheV2AckSubject), which is also what caught the first draft of the regression below silently not testing a domain at all.
Regressions, all verified to fail on the previous logic:
- cross-domain re-capture on TWO real brokers, because it needs two: hop 1 in a domainless deployment, its record moved into a domained one, hop 2 there. Under per-field absence the record comes back claiming origin domain "hub";
- the same defect for metadata-less origins, where per-field absence has the record naming the DLQ stream and the DLQ's own sequence as the message's origin.
Refs ENT-1601, ENT-1535, ENT-1492, COR-1257.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com Claude-Session: https://claude.ai/code/session_018qXhU99D2Sxaa32yZWwYRP Entire-Checkpoint: 445355479b5a