Envelope
The instrumentation envelope stamped onto every event.
Transports place it under context.instrumentation (or equivalent) and may reuse eventId as their message id for deduplication.
Produced by the library, never constructed by callers. The constructor (and with it copy) is internal so that new envelope fields stay binary-compatible additions for every caller the compiler governs — see ../../../../../../../docs/adr/0001-public-api-evolution.md §2a, which records the one place that does not hold. A transport that needs an envelope calls EnvelopeSource.stamp; building one by hand would bypass event-id uniqueness, session rotation, and sequence monotonicity, which is the whole value of the type. Tests construct envelopes with testEnvelope(...) from autograph-test.
New properties are appended at the end. That is binary-compatible but not behavior-compatible: it changes what equals/hashCode/toString mean, so a caller keying a map on an envelope sees a change with no compile error.
Properties
Unique event id, from the configured EventIdGenerator.
When the app fired this event, as an ISO-8601 UTC instant. Captured at the track/screen/identify call site (on the caller's thread), so it is independent both of the serial dispatcher's own stamping lag and of whatever event-time field the transport ends up stamping — either of which can lag behind by however long they batch/enqueue before sending. (Transports that stamp inside their own pipeline record their processing time here instead, since the app's call time isn't available to them.) Precision matches the platform clock backing kotlin.time.Clock.System (millisecond resolution on the JVM and Android; may be finer on other targets), not a guaranteed nanosecond timestamp.
The consumer's own event-schema version, from AutographConfig.schemaVersion, or null when unset. Distinct from sdk: this versions the adopter's tracking plan/contract, not the library.
The session this event belongs to.