Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_sbj/src/lib.rs

6.5 KiB, 21 runs

created by r1870400018:22222, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1//! SBJ, Signed Binary JDAT: the file format of the oxeweb.
2//!
3//! An SBJ file is a signed envelope wrapping a tree of typed nodes encoded in BDAT, JDAT's binary
4//! form. The hash of the tree region is the document's permanent address, and the envelope's
5//! signature binds that address to its author.
6//!
7//! The normative description is `SPEC.md` beside this crate. Where the two disagree, this code is
8//! wrong.
9//!
10//! The container is not specific to documents. An envelope declares the schema of its payload, so
11//! an oxeweb document (`oxeweb/doc/0`) and a signed administrative command are the same artefact
12//! with different payloads and different validators.
13
14pub mod canon;
15pub mod card;
16pub mod doc;
17pub mod envelope;
18pub mod import;
19pub mod index;
20pub mod key;
21pub mod kinds;
22pub mod post;
23pub mod prelude;
24pub mod share;
25pub mod text;
26pub mod validate;
27
28/// File magic, `SBJ\0`.
29pub const MAGIC: [u8; 4] = [0x53, 0x42, 0x4A, 0x00];
30
31/// Format major version implemented here.
32pub const VERSION_MAJOR: u16 = 0;
33
34/// Fixed header length in bytes: magic, major version, envelope length.
35pub const HEADER_LEN: usize = 8;
36
37/// Schema identifier for an oxeweb document payload, which admits the kinds 1 to 13 and no others.
38pub const SCHEMA_DOC: &'static str = "oxeweb/doc/0";
39
40/// Schema identifier for the browser's own chrome, which admits the document kinds and the `edit`
41/// node (§4.2).
42pub const SCHEMA_CHROME: &'static str = "oxeweb/chrome/0";
43
44/// Schema identifier for an application's tree, which admits the document kinds, the `edit` node and
45/// the `surface` node (§4.2).
46pub const SCHEMA_APP: &'static str = "oxeweb/app/0";
47
48/// Schema identifier for a signed message payload, which is a record rather than a node tree.
49///
50/// The first payload here that is not a document, and the reason the container names its schema
51/// inside the signing input: a message and a document are the same artefact with different
52/// payloads and different validators, and neither can be re-labelled as the other after signing.
53pub const SCHEMA_POST: &'static str = "daimond/post/0";
54
55/// Schema identifier for a self-signed identity card.
56///
57/// A card is what a QR code and a paste carry, where a bare public key cannot: it says which key
58/// seals and which signs, carries a display label, and names the key it supersedes. It verifies
59/// under the key it carries, which proves the holder composed it and proves nothing at all about
60/// who the holder is.
61pub const SCHEMA_CARD: &'static str = "daimond/card/0";
62
63/// Schema identifier for one person sending another a copy of something they own.
64///
65/// Implemented by [`share`], which carries the files, the display name, and the consent bit that
66/// says whether any of those files is a program. **A share is a COPY the receiver comes to own**:
67/// re-sealed to their key, landing in their workspace as theirs, changeable by them and never seen
68/// again by the sender. It is not a live view, so there is no content key that survives an edit,
69/// nothing to revoke, and nobody's storage to argue about but the receiver's own.
70///
71/// # Why this is a schema and not a fifth reference kind
72///
73/// The obvious-looking alternative is a fifth arm on [`post::Target`], and it is wrong three times
74/// over.
75///
76/// A share **carries** what it sends. The thing shared is a copy the receiver comes to own, sealed
77/// to their key, and a [`post::Reference`] is a pointer with a fallback sentence — four of them per
78/// message, each field capped at 128 bytes. There is nothing to point AT: the content travels.
79///
80/// A share is **private**. The four reference kinds are public anchors, globally named and
81/// resolvable by anybody holding a session, and [`post::Target`] says in its own documentation that
82/// private, device-local pointers are deliberately absent, because the other party cannot
83/// dereference one and an interface must never draw a pressable chip that will always fail. A fifth
84/// arm for a private object would make that sentence false.
85///
86/// And a share must carry **a consent bit that the signature covers**. Where the thing shared holds
87/// executable content, the receiver decides whether to run it, and they can only decide honestly if
88/// they can check that the SENDER marked it — a flag a relay could add or strip is not a consent
89/// flag. A `Reference` has room for no such thing: it carries exactly two keys, and `from_dat`
90/// refuses a third. That is the argument that settles it, since the other two might be argued
91/// around and this one cannot.
92///
93/// # Why adding it cost nothing signed
94///
95/// A schema name reaches the signing input length-prefixed (§1.3), so a third name is unambiguous
96/// against every artefact already signed under the first two: no post and no card in existence is
97/// weakened, re-addressed or made forgeable by this name coming to exist. That is precisely what
98/// the length prefix bought, and it is why this could be reserved in a comment first and
99/// implemented afterwards with no migration, and with every fixture already committed staying
100/// byte for byte the file it was.
101pub const SCHEMA_SHARE: &'static str = "daimond/share/0";
102
103/// Limits enforced before a document is trusted. See `SPEC.md` §5.
104pub mod limit {
105 /// Maximum size of the tree region, in bytes.
106 pub const TREE_BYTES: usize = 4 * 1024 * 1024;
107 /// Maximum size of the envelope region, in bytes.
108 pub const ENVELOPE_BYTES: usize = 4 * 1024;
109 /// Maximum number of nodes in a tree.
110 pub const NODES: usize = 100_000;
111 /// Maximum number of `surface` nodes in one tree (§4.2).
112 ///
113 /// A surface is the one place in the format where something other than the author's data reaches
114 /// the screen, and every one of them is a live application instance the host must lay out, budget
115 /// and present. The number is revisable on evidence, like every other limit here; the commitment
116 /// made now is that there is one, since a tree that may open unboundedly many instances is a tree
117 /// that may exhaust the host by being opened.
118 pub const SURFACES: usize = 8;
119 /// Maximum nesting depth, enforced by the decoder before verification.
120 ///
121 /// Set so that a document at the ceiling decodes within a standard 2 MiB worker-thread stack,
122 /// since a recursive decoder spends a frame per level and a stack overflow aborts the process
123 /// rather than returning an error. Sixty-four levels of document nesting is already far beyond
124 /// anything real, where a deeply structured document reaches perhaps twenty, and it matches the
125 /// default depth limit of the BDAT decoder in `fe2o3_jdat`.
126 pub const DEPTH: usize = 64;
127}