hecate_om_ownership_proof (hecate_om v0.24.0)
View SourceVerifies a caller actually holds the private key for the Ed25519 identity (a raw 32-byte pubkey -- the same node_id/DID convention macula's own identity uses) it claims to be asserting on behalf of, inside an otherwise-open mesh payload.
A Macula identity is literally an Ed25519 public key (macula_identity:node_id() :: pubkey()`), so ownership is proved by signing `{identity, timestamp, procedure}` with the matching private key -- `procedure` included so a proof minted for one gated capability cant be replayed against another this or any other service adds later.
Extracted here after the identical ~40-line verifier had been written twice independently -- hecate-citizens' citizen_ownership_proof` (proving a `register_presence` caller holds the `citizen_did` its registering) and hecate-mail's mailbox_ownership_proof` (proving a caller may read a mailbox) -- each ones own moduledoc naming the same test for when to stop duplicating it: "would a second, unrelated consumer plausibly want this same fact." hecate-graph's learn_link` needing it too (to make graph provenance mind-grained rather than only connection-grained, PLAN_MESH_TRUTHS_AND_PROVENANCE.md) is the third consumer that crosses it. A DIFFERENT mechanism from maculas own {ucan_required, Issuer}` capability gating (`hecate-om/plans/PLAN_UCAN_GATED_CAPABILITIES.md`): that controls who may CALL a procedure at all, enforced by the serving station before any handler runs. This proves WHO ASSERTED a specific claim inside an otherwise-open procedures payload -- provenance, not access control. A procedure can use either, both, or neither.
WIRE ENCODING: macula's frame decoder walks a payload map and converts every CBOR TEXT value to an ATOM via binary_to_existing_atom/1 whenever the RECEIVING VM already has that atom loaded -- if not, it stays a {text, Binary} tuple. Which shape a given value arrives as therefore depends on what atoms this VM happens to already know, not on anything the caller controls: a real identity (effectively random hex) is essentially never already an atom, so it always arrives {text, Bin}-tagged. unwrap_text/1 handles all three shapes (bare binary, bare atom, {text, Bin}) plus undefined; decode_identity/1 layers hex-decoding on top for identity/signature fields, decode_text/1 is the same unwrap alone for any other wire-transported string.
Summary
Functions
Unwraps, then hex-decodes, a wire-transported identity (or signature) into its raw bytes.
unwrap_text/1 alone, for any wire-transported string that isn't an identity/signature.
Verify that Proof (a map with timestamp and signature) proves possession of the private key behind Identity (a raw 32-byte Ed25519 pubkey), bound to Procedure.
Functions
Unwraps, then hex-decodes, a wire-transported identity (or signature) into its raw bytes.
unwrap_text/1 alone, for any wire-transported string that isn't an identity/signature.
Verify that Proof (a map with timestamp and signature) proves possession of the private key behind Identity (a raw 32-byte Ed25519 pubkey), bound to Procedure.