Skip to content

Commit 6ea219b

Browse files
committed
Update envelope notation paper with code fence tags and subject guidance
Add "envelope" language identifier to all code fence blocks for syntax highlighting. Add new section documenting the use of UUID, null, and 'unknown' as envelope subjects for identified, unidentified, and unknown-identity entities respectively.
1 parent 94d3cc1 commit 6ea219b

1 file changed

Lines changed: 65 additions & 35 deletions

File tree

papers/bcr-2026-002-envelope-notation.md

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ This document is intended to be read by humans and AI agents. It is *not* a form
2121

2222
An envelope is a *subject* with multiple *assertions*. Each assertion asserts a *fact* about the subject. Square brackets `[` and `]` denote the start and end of the assertions for a subject. There are no line terminators or commas between assertions.
2323

24-
```
24+
```envelope
2525
<subject> [
2626
<assertion>
2727
<assertion>
@@ -32,7 +32,7 @@ An envelope is a *subject* with multiple *assertions*. Each assertion asserts a
3232

3333
Assertions are composed of a *predicate* and an *object*, separated by a colon `:`.
3434

35-
```
35+
```envelope
3636
<subject> [
3737
<predicate>: <object>
3838
<predicate>: <object>
@@ -47,21 +47,21 @@ $$(subject, predicate, object) \in Envelope$$
4747

4848
A subject can have no assertions (a *bare subject*):
4949

50-
```
50+
```envelope
5151
<subject>
5252
```
5353

5454
Brackets always contain one or more assertions. An envelope with no assertions *must* omit the brackets entirely.
5555

5656
An assertion can also stand alone (a *bare assertion*):
5757

58-
```
58+
```envelope
5959
<predicate>: <object>
6060
```
6161

6262
An envelope can be *wrapped*. The wrapped subject *and* its assertions become the subject of the envelope. It is denoted by enclosing the entire subject and its assertions in curly braces `{` and `}`.
6363

64-
```
64+
```envelope
6565
{
6666
<subject> [
6767
<assertion>
@@ -72,7 +72,7 @@ An envelope can be *wrapped*. The wrapped subject *and* its assertions become th
7272

7373
This allows assertions to be placed on the entire wrapped envelope. Below, `inner-assertion`s are assertions about the *subject* of the inner envelope, while `outer-assertion`s are assertions about the *entire inner envelope*. This pattern is commonly used when signing.
7474

75-
```
75+
```envelope
7676
{
7777
<subject> [
7878
<inner-assertion>
@@ -95,15 +95,15 @@ Every *position* within an envelope is *also itself* an envelope. So every posit
9595

9696
Subject with an assertion (most common):
9797

98-
```
98+
```envelope
9999
<subject> [
100100
<predicate>: <object>
101101
]
102102
```
103103

104104
Wrapped envelope with an assertion (common):
105105

106-
```
106+
```envelope
107107
{
108108
<subject> [
109109
<inner-assertion>
@@ -115,7 +115,7 @@ Wrapped envelope with an assertion (common):
115115

116116
Object with an assertion (common):
117117

118-
```
118+
```envelope
119119
<subject> [
120120
<predicate>: <object> [
121121
<object-assertion>
@@ -125,7 +125,7 @@ Object with an assertion (common):
125125

126126
Predicate with an assertion (rare):
127127

128-
```
128+
```envelope
129129
<subject> [
130130
<predicate> [
131131
<predicate-assertion>
@@ -136,7 +136,7 @@ Predicate with an assertion (rare):
136136

137137
Assertion with an assertion (less common):
138138

139-
```
139+
```envelope
140140
<subject> [
141141
{
142142
<predicate>: <object>
@@ -174,13 +174,13 @@ Because Envelope Notation is a human-readable format, the envelope formatter may
174174

175175
A bare subject that is a leaf displays just the leaf value. This is the notation for a simple but complete envelope:
176176

177-
```
177+
```envelope
178178
"Just a string"
179179
```
180180

181181
Here `UUID` and `Date` are known tagged CBOR types, so they are displayed with their canonical names and formatted values:
182182

183-
```
183+
```envelope
184184
UUID(dd1aaad2-0ae6-4402-9806-f60ba7a51361) {
185185
'isA': "HeartRateMeasurement"
186186
'date': Date(2026-01-15T10:30:00Z)
@@ -194,15 +194,15 @@ UUID(dd1aaad2-0ae6-4402-9806-f60ba7a51361) {
194194

195195
For example, the known value `1` has the canonical name `isA`, and is used as a predicate to assert the type of a subject. By noticing what kinds of quotes are used, the reader can immediately see that `'isA'` is a known value and `"SomeType"` is a string:
196196

197-
```
197+
```envelope
198198
<subject> [
199199
'isA': "SomeType"
200200
]
201201
```
202202

203203
If the envelope formatter encounters an *unknown* known value, it will display the known value's integer code point in single quotes:
204204

205-
```
205+
```envelope
206206
<subject> [
207207
'9999': "No idea what's being asserted here"
208208
]
@@ -214,14 +214,44 @@ Known value code points have been assigned to many common concepts, as well as t
214214

215215
Known value `0` represents the [Unit](https://grokipedia.com/page/Unit_type), which is a type as well as its sole inhabitant. It is used to denote not merely the *absence* of a value (that is what `null` is for), but to hold a position where there *can* be no information conveyed and it would be *invalid* to do so. It is displayed as empty single quotes `''`. The most common use of Unit is as the subject of an envelope entirely defined by its assertions:
216216

217-
```
217+
```envelope
218218
'' [
219219
'isA': 'foaf:Person'
220220
'foaf:firstName': "Alice"
221221
'foaf:lastName': "Smith"
222222
]
223223
```
224224

225+
In the case where such a structure has a unique identifier for the referent, the subject may instead be a known value representing the unique identifier, e.g. a UUID, or XID:
226+
227+
```envelope
228+
UUID(a25e5f24-33e2-41ba-b5c3-61c7d630620a) [
229+
'isA': 'foaf:Person'
230+
'foaf:firstName': "Carol"
231+
'foaf:lastName': "Johnson"
232+
]
233+
```
234+
235+
Where a unique identifier is not available, `null` may be used as the subject to indicate the envelope refers an unidentified entity where the identifier may or may not exist:
236+
237+
```envelope
238+
null [
239+
'isA': 'foaf:Person'
240+
'foaf:firstName': "Bob"
241+
'foaf:lastName': "Jones"
242+
]
243+
```
244+
245+
The `'unknown'` known value is used to indicate that the identifier *must* exist, but is not known:
246+
247+
```envelope
248+
'unknown' [
249+
'isA': 'foaf:Person'
250+
'foaf:firstName': "Eve"
251+
'foaf:lastName': "Unknown"
252+
]
253+
```
254+
225255
## Obscuring
226256

227257
Envelopes may be *obscured* in three different ways: *elision*, *encryption*, and *compression*. The critical property is that even though the content may be obscured, the Merkle-like digest tree of the envelope remains intact, allowing integrity verification and selective disclosure.
@@ -234,61 +264,61 @@ In the examples below `<OBSCURED>` can appear as `ELIDED`, `ENCRYPTED`, or `COMP
234264

235265
No positions obscured:
236266

237-
```
267+
```envelope
238268
"Alice" [
239269
'foaf:knows': "Bob"
240270
]
241271
```
242272

243273
Subject obscured:
244274

245-
```
275+
```envelope
246276
<OBSCURED> [
247277
'foaf:knows': "Bob"
248278
]
249279
```
250280

251281
Predicate obscured:
252282

253-
```
283+
```envelope
254284
"Alice" [
255285
<OBSCURED>: "Bob"
256286
]
257287
```
258288

259289
Object obscured:
260290

261-
```
291+
```envelope
262292
"Alice" [
263293
'foaf:knows': <OBSCURED>
264294
]
265295
```
266296

267297
Predicate and object obscured:
268298

269-
```
299+
```envelope
270300
"Alice" [
271301
<OBSCURED>: <OBSCURED>
272302
]
273303
```
274304

275305
Entire assertion obscured:
276306

277-
```
307+
```envelope
278308
"Alice" [
279309
<OBSCURED>
280310
]
281311
```
282312

283313
Entire envelope obscured:
284314

285-
```
315+
```envelope
286316
<OBSCURED>
287317
```
288318

289319
When more than one assertion has been obscured in the same way, they are grouped together for brevity. Here five assertions have been elided, but their digests remain separately verifiable:
290320

291-
```
321+
```envelope
292322
"Alice" [
293323
ELIDED (5)
294324
]
@@ -298,7 +328,7 @@ When more than one assertion has been obscured in the same way, they are grouped
298328

299329
In a Gordian Envelope, each assertion must have a unique digest. In other words, no two assertions can be identical. Because Envelope Notation can abbreviate values for readability, it may appear that duplicate assertions exist when they do not. For example, here are two assertions that *look* identical, but actually *must* have different byte strings for the objects:
300330

301-
```
331+
```envelope
302332
<subject> [
303333
'key': Bytes(16)
304334
'key': Bytes(16)
@@ -313,7 +343,7 @@ The important thing to remember is that in a Gordian Envelope, assertions are *u
313343

314344
Signatures are assertions. But as assertions assert facts about their subjects, an envelope like this would not sign the whole envelope, but only the subject.
315345

316-
```
346+
```envelope
317347
<subject> [
318348
<inner-assertion>
319349
'signed': Signature
@@ -322,7 +352,7 @@ Signatures are assertions. But as assertions assert facts about their subjects,
322352

323353
To sign the entire envelope, including its assertions, the common pattern is to *wrap* the envelope first, then place the signature assertion on the outer envelope:
324354

325-
```
355+
```envelope
326356
{
327357
<subject> [
328358
<inner-assertion>
@@ -338,7 +368,7 @@ The plaintext envelope is optionally signed, then symmetrically encrypted with t
338368

339369
Plaintext signed then wrapped:
340370

341-
```
371+
```envelope
342372
{
343373
{
344374
<subject> [
@@ -352,13 +382,13 @@ Plaintext signed then wrapped:
352382

353383
The subject (now the entire signed envelope) is then encrypted using the content key:
354384

355-
```
385+
```envelope
356386
ENCRYPTED
357387
```
358388

359389
The encrypted envelope is then asserted for each recipient:
360390

361-
```
391+
```envelope
362392
ENCRYPTED [
363393
'hasRecipient': SealedMessage
364394
'hasRecipient': SealedMessage
@@ -369,7 +399,7 @@ ENCRYPTED [
369399

370400
A password may be used to symmetrically encrypt the content key. The `hasSecret` assertion contains an `EncryptedKey` object with the encrypted content key and necessary parameters.
371401

372-
```
402+
```envelope
373403
ENCRYPTED [
374404
'hasSecret': EncryptedKey(Argon2id)
375405
]
@@ -379,7 +409,7 @@ ENCRYPTED [
379409

380410
Before elision the assertion object is decorated with a salt assertion to prevent identical objects from producing identical digests.
381411

382-
```
412+
```envelope
383413
<subject> [
384414
{
385415
<predicate>: <object>
@@ -391,7 +421,7 @@ Before elision the assertion object is decorated with a salt assertion to preven
391421

392422
After elision the digest remains, but the salt prevents correlation.
393423

394-
```
424+
```envelope
395425
<subject> [
396426
ELIDED
397427
]
@@ -403,7 +433,7 @@ After elision the digest remains, but the salt prevents correlation.
403433

404434
Example: a cryptographic seed envelope with two attachments, each conforming to a different version of a seed attachment format, along with a name and note assertions:
405435

406-
```
436+
```envelope
407437
Bytes(16) [
408438
'isA': 'Seed'
409439
'attachment': {
@@ -443,7 +473,7 @@ Envelope notation uses some punctuation characters in ways that are overloaded b
443473

444474
## Mock Example: Supply Chain Manifest
445475

446-
```
476+
```envelope
447477
{
448478
UUID(550e8400-e29b-41d4-a716-446655440000) [
449479
'isA': "ElectronicComponent"

0 commit comments

Comments
 (0)