// FILE: ./internal/normalizers/common/finalize.go package common import ( "time" "gitea.maximumdirect.net/ejr/feedkit/event" ) // Finalize builds the output event envelope by copying the input and applying the // canonical schema/payload, plus (optionally) EffectiveAt. // // Important behavior: // - ID/Kind/Source/EmittedAt are preserved by copying the input event. // - EffectiveAt is only overwritten when effectiveAt is non-zero. // If effectiveAt is zero, any existing in.EffectiveAt is preserved. // - Payload floats are rounded to a stable wire-friendly precision (see round.go). func Finalize(in event.Event, outSchema string, outPayload any, effectiveAt time.Time) (*event.Event, error) { out := in out.Schema = outSchema // Enforce stable numeric presentation for sinks: round floats in the canonical payload. out.Payload = RoundFloats(outPayload, DefaultFloatPrecision) if !effectiveAt.IsZero() { t := effectiveAt.UTC() out.EffectiveAt = &t } if err := out.Validate(); err != nil { return nil, err } return &out, nil }