Append Semantics¶
This document freezes the observable write-path behavior of the Python reference implementation.
Append Pipeline¶
For every incoming EventEnvelope, the reference implementation does the following in order:
- validate the idempotency key
- validate payload JSON safety
- validate payload shape for the chosen event type
- scan payload and selected metadata through the PII guard
- compute canonical payload hash
- serialize payload and tags to JSON
- compute
recorded_at - enforce idempotency semantics
- enforce trace sequencing semantics
- enforce
TraceFinishedlocking - persist and return
StoredEvent
Idempotency¶
Idempotent reuse is scoped by the backend-specific uniqueness rule and then validated against the stored event.
The reference behavior requires:
- payload hash must match exactly
trace_idmust matchevent_typemust matchsourcemust matchactormust matchcorrelation_idmust matchcausation_event_idmust matchschema_versionmust matchtagsmust match
trace_seq is intentionally excluded from idempotent-reuse matching. This is a frozen behavior and future ports must preserve it.
Trace Sequencing¶
- the next event for a trace must use the exact next
trace_seq TraceStartedmust usetrace_seq = 0- no non-
TraceStartedevent may usetrace_seq = 0
These rules are part of the append contract, not merely a projector concern.
TraceFinished Lock¶
Once a trace contains TraceFinished, later appends to that trace must be rejected.
This lock is part of the semantic contract for all backends.
Hash and Timestamp Semantics¶
payload_hashis computed from canonical payload JSON onlyoccurred_atcomes from the caller and is part of the semantic event recordrecorded_atis storage-time metadata and is not part of deterministic digest comparison
Error Semantics¶
Backends may differ in implementation details, but they must preserve the same behavior categories:
- invalid arguments
- schema violations
- PII-policy violations
- idempotency conflicts
- sequence errors
- storage conflicts such as post-finish writes
Exact human-readable error text may evolve, but the observable failure mode must not.