Hi Orie, Here’s the “Person → Employment → Company” fact expressed in Gordian Envelope, using two specific patterns we’ve defined:
* ARIDs – random, implementation‑agnostic identifiers https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2022-002-arid.md * Signature‑with‑Metadata – four‑step recipe for binding a signature, its metadata, and the payload https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2024-009-signature-metadata.md --- ### 1 Observation payload ARID(<obs‑id>) [ 'isA' : "Observation" 'type' : "Employment" 'of' : ARID(<alice>) 'date' : 2021‑01‑01 ] ARIDs are random, used to identify objects that can mutate over time. If you want the subject to refer to a record that is immutable and content-addressable, you can use a `Digest` as the subject. The payload is wrapped so it can be signed as a whole. The braces signify that the *entire* envelope, including its assertions are a single subject that can have additional assertions added to it, and that apply as a whole: { ARID(<obs‑id>) [ 'isA' : "Observation" 'type' : "Employment" 'of' : ARID(<alice>) 'date' : 2021‑01‑01 ] } --- ### 2 Bob’s signature + metadata { Signature(<bob>) [ // sig over observation digest (from the wrapped envelope above) 'signer' : ARID(<bob>) 'purpose' : "observedBySigner" 'validFrom' : 2021‑01‑01 'validUntil': 2022‑01‑01 ] } [ 'signed' : Signature(<bob>) // sig over metadata digest (the signature + metadata envelope) ] --- ### 3 Attach the signature to the observation The 'signed': { ... } is a *single assertion* that is added to the original wrapped observation. { ARID(<obs‑id>) [ 'isA' : "Observation" 'type' : "Employment" 'of' : ARID(<alice>) 'date' : 2021‑01‑01 ] } [ 'signed' : { Signature(<bob>) [ // sig over observation digest 'signer' : ARID(<bob>) 'purpose' : "observedBySigner" 'validFrom' : 2021‑01‑01 'validUntil': 2022‑01‑01 ] } [ 'signed' : Signature(<bob>) // sig over metadata digest ] ] A verifier checks two signatures with Bob’s key—one on the observation, one on the metadata. Both must be made with the same private key. --- ### 4 Optional elision Subscribers to the stream might only see the ID of the observation and who authenticated it, but not the observations themselves. Envelopes can be elided or encrypted at any granularity, and because signatures cover the digest, they still verify even when the content is elided or encrypted. And you can always replace any `ELIDED` branch with some or all of its original content, enabling progressive disclosure. { ARID(<obs‑id>) [ ELIDED (4) // Envelope shorthand: four elided assertions collapsed onto a single line ] } [ 'signed' : { Signature(<bob>) [ // sig over observation digest 'signer' : ARID(<bob>) 'purpose' : "observedBySigner" 'validFrom' : 2021‑01‑01 'validUntil': 2022‑01‑01 ] } [ 'signed' : Signature(<bob>) // sig over metadata digest ] ] --- Would you agree this addresses the issues you envisioned? * No forced canonicalization – the inner JWT/CBOR/whatever stays byte‑for‑byte. * Hash‑addressed substitution / elision – any branch can be replaced by `ELIDED`; signatures remain valid. * Signer‑subject linkage – explicit `'signer'` field, and the outer signature binds the metadata to the attestation, while keeping it severable. * Any envelope can have a `’salt’: ` assertion added to it to decorrelate its contents from its digest. * Multiple signers – just add parallel `'signed'` assertions, each embedding its own metadata envelope, without touching the original event. * Replica reconciliation (future work) – because envelopes are immutable and hash‑addressed, they lend themselves to CRDT‑style set‑union sync: peers could exchange their replicas and make the union, with conflicting facts persisting side‑by‑side until resolved by a follow‑up assertion (e.g., 'contradicts', 'supersedes'). We haven’t built the reference code yet, but the data model is designed to support it. You may also find this interesting: * Representing Graphs using Gordian Envelope: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2024-006-envelope-graph.md ~ Wolf > On Apr 16, 2025, at 8:07 PM, Orie <o...@or13.io> wrote: > > Trimming CC. > > I'm wearing no hats for this rant. > > We seemed to have stumbled on one of my favorite topics. > > Authenticated hypergraphs. > > Imagine a stream of events, each event is an observation, signed by an > observer. > > The stream is partially observable to subscribers. > > Each subscriber assembles the events into a belief network. > > In these systems, it's a nice feature to agree on identifiers for subjects > and objects. > > Its also a nice property to be able to match the key material signing or > decrypting events to the subjects or objects. > > But how do you handle conflicting information, merging and consistency over > time? > > Consider this small fragment of cypher: > > MATCH (p:Person)-[r:WORKS_AT {since: 2021}]->(c:Company) > RETURN p.name <http://p.name/> AS Employee, c.name <http://c.name/> AS > Company, r.role AS Role > > For a query like this, you might want to know which events contribute to the > result, who signed them, and for how long should the information be > considered valid. > > You can do this with any container format. > > You don't need embedded signatures to do this. > > Another design consideration is being able to replace a large event with a > unique identifier. > > In order to do that, and still have useful and interesting events people turn > to general purpose canonicalization. > > Meanwhile, most of the interesting events are still JWTs, PGP, CMS, normal > COSE, etc... > > Real data is often not in a canonical form. > > People create map keys as they need them, and they like putting "title" > before "description" even though that's not how they sort lexicographically. > > Canonicalization eliminates ways that data can exist. > > Cryptography preserves data as it exists. > > Naively combining them just eliminates sources of useful information. > > For those who want to add embedded signatures to any packaging format. > > 1. Define the parameter name. > 2. Write down the rules for creating and validating it (canonicalization) > 3. Describe how to embed and extract signatures. > > If you want to do chains (ordered counter signatures) you need a way to > signal the order of the signatures, and rules for how to verify. > > The rules don't need to be complicated. > > If you want to embed the identifiers for the resource and make them hash > based, another layer of application specific rules. > > Ohh but we want redaction too, let's add salted hashes to all the predicates. > > { > id: (magic determinsitic id) > subject: { predicate: object } > signature: [ ... , > { ..., key_id, valid_from, valid_until } > ] > } > > You basically end with event sourced progressively disclosable attribute cert > derived labeled property graphs. > > As soon as you're done making this system, somebody will want to simply sign > data without making any changes to it, and you'll be back to enveloped > signatures. > > OS > > > On Wed, Apr 16, 2025, 5:31 PM Wolf McNally <w...@wolfmcnally.com > <mailto:w...@wolfmcnally.com>> wrote: >> Vadim, >> >> > On Apr 16, 2025, at 1:26 PM, Vadim Goncharov <vadimnucli...@gmail.com >> > <mailto:vadimnucli...@gmail.com>> wrote: >> > >> > Essentially known-values are just another way to specify a compact encoding >> > for long type string, like JSON-LD does for URIs, so a generic >> > (semantic) compaction framework like CBAPT can replace many wheels >> > reinvented >> > again and again in protocols, leaving only thin amount for them to define. >> >> I think I understand you correctly, so yes. >> >> Many semantic systems use “triples”: >> >> <subject> <predicate> <object> >> “Sam” ‘knows' “John” >> >> Where predicates like ‘knows’ are common, and in some cases universal. >> >> Gordian Envelope is based on the pattern: >> >> <subject> [ >> <predicate>: <object> >> <predicate>: <object> >> ... >> ] >> >> (Note the above is “Envelope Notation”, not CBOR diagnostic notation or >> CDDL). Gordian Envelope itself is built on dCBOR. >> >> Where a number of assertions (<predicate>: <object> pairs) are declared on a >> subject, and any of these positions can be a dCBOR object, including nested >> Gordian Envelopes, forming a tree with a unique digest at every node. >> >> Strings (like URLs) can work for predicates, but can take up significant >> space, and where URLs can be specified numerous ways, this can lead to >> breaking determinism. So we created the known-value space #6.40000 which is >> always just a tagged 64-bit integer. The length of a known-value with a 1+1 >> integer is only 5 bytes. >> >> So we’re making first-come first-served assignments of code points in the >> known-value space for anyone who would find such a value useful that is >> fixed public, and globally unique, and can provide a URL to a spec claiming >> it, with no reasonable request refused. >> >> I need to emphasize that there is nothing about known-values that tie them >> to dCBOR or Gordian Envelope (other than that they are compatible with any >> kind of CBOR.) You can use them as keys in CBOR maps, or anywhere you want >> an integer value that is unique and has fixed semantics. >> >> https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2023-002-known-value.md >> >> ~ Wolf >> _______________________________________________ >> CBOR mailing list -- c...@ietf.org <mailto:c...@ietf.org> >> To unsubscribe send an email to cbor-le...@ietf.org >> <mailto:cbor-le...@ietf.org> > _______________________________________________ > CBOR mailing list -- c...@ietf.org > To unsubscribe send an email to cbor-le...@ietf.org
_______________________________________________ COSE mailing list -- cose@ietf.org To unsubscribe send an email to cose-le...@ietf.org