morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
payload_schema.hpp File Reference

Structural fingerprint of an action payload's JSON shape. More...

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <glaze/glaze.hpp>
#include <morph/core/payload_shape_tag.hpp>
#include <optional>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

Go to the source code of this file.

Functions

template<typename A>
const std::string & morph::model::payloadShapeString ()
 Returns the human-readable shape rendering behind payloadFingerprint<A>().
template<typename A>
const std::string & morph::model::payloadFingerprint ()
 Returns A's payload fingerprint: "<scheme>:<16 hex digits>".

Variables

constexpr std::uint32_t morph::model::kPayloadFingerprintScheme = 2
 Version of the fingerprint algorithm, not of any one payload.

Detailed Description

Structural fingerprint of an action payload's JSON shape.

The journal records an action's request as JSON and replays it, later, through ActionTraits<A>::fromJson — a lenient decode that ignores unknown keys and default-constructs absent ones. That leniency is deliberate (it is what makes an additive field a non-event for every already-deployed reader), but on the replay path it also means a renamed field silently becomes "key absent + unknown key ignored": the entry decodes, the model reconstructs, and the value that was actually recorded is gone. Nothing in the entry said which shape wrote it, so nothing could notice.

This header supplies the missing discriminator: a short, stable string derived from the payload struct's reflected shape, cheap enough to stamp on every recorded entry and compare on every replayed one. See docs/spec/journal/journal.md, "Payload schema fingerprint".

Definition in file payload_schema.hpp.

Function Documentation

◆ payloadShapeString()

template<typename A>
const std::string & morph::model::payloadShapeString ( )
inlinenodiscard

Returns the human-readable shape rendering behind payloadFingerprint<A>().

Exposed because a fingerprint mismatch is otherwise two opaque hex strings: with this, a diagnostic (or a developer at a prompt) can print both shapes and see which member moved. Not stamped on entries — it is unbounded in length, whereas the fingerprint is 18 bytes.

Template Parameters
AAction payload type.
Returns
The shape rendering; see detail::payloadShape for the grammar.

Definition at line 249 of file payload_schema.hpp.

◆ payloadFingerprint()

template<typename A>
const std::string & morph::model::payloadFingerprint ( )
inlinenodiscard

Returns A's payload fingerprint: "<scheme>:<16 hex digits>".

Two payload types fingerprint identically exactly when payloadShapeString() renders them identically — i.e. when they have the same member names, at the same nesting positions, with the same JSON-shape tags. Computed once per type per process (a function-local static) and returned by reference; stamping it on a journal entry is a string copy of 18 bytes.

Template Parameters
AAction payload type.
Returns
Reference to the process-lifetime fingerprint string for A.

Definition at line 266 of file payload_schema.hpp.

Variable Documentation

◆ kPayloadFingerprintScheme

std::uint32_t morph::model::kPayloadFingerprintScheme = 2
inlineconstexpr

Version of the fingerprint algorithm, not of any one payload.

Stamped as the prefix of every fingerprint ("2:…") so a future build that computes fingerprints differently can still recognise — and reject, or re-derive — a fingerprint written under an earlier scheme, instead of mistaking a scheme change for a payload change. Bumped only when detail::payloadShape changes what it emits for an unchanged struct.

Scheme 2 renders a custom-codec type that declares a morph::model::PayloadShapeTag as that declared name rather than as the bare opaque tag, so that a retype between two of them is visible. Every payload with such a member therefore fingerprints differently under 2 than it did under 1, which is exactly what the prefix exists to make legible: an entry stamped 1:… read by this build reports a mismatch that names an algorithm change, not a payload change.

Definition at line 50 of file payload_schema.hpp.