1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! **A new box's material** (yog's `docs/REMOTE.md` §8.4) — the six fields the
//! `enroll` act answers, and the one envelope a camera carries them in.
//!
//! # The reply this seat must not keep
//!
//! Every other kind in this vocabulary is something the window draws and may
//! redraw. This one carries a **private key that is not this box's** — minted
//! on the engine's CA for a device that does not exist yet — and the seat's
//! whole job with it is to put it on a screen and forget it. Nothing here
//! writes, caches or logs; [`Enrolled`] is a value the window holds while a
//! symbol is on screen and drops with the pane. See DESIGN §3.
//!
//! # The envelope is a re-saying, not a second field list
//!
//! [`Enrolled::envelope`] is here rather than beside the QR encoder for one
//! reason: it names the same six fields the reader above it names, and two
//! lists of one field set drift. REMOTE §8.4 is the authority for its shape and
//! this module implements it:
//!
//! - **compact JSON**, no whitespace;
//! - the six fields **verbatim**, PEM as minted — DER-plus-base64 was measured,
//! buys about a tenth of the bytes and costs the property worth keeping,
//! which is a field an operator can paste into `openssl x509 -text`;
//! - under `"yog-enroll": 1`, the marker a scanner recognises it by and the
//! version it will be told about if the fields ever move;
//! - and **without `ok` and `kind`**, which say what a *wire answer* is. A
//! photograph is not one.
//!
//! Key order is `serde_json`'s own, which is sorted, and that is the same order
//! the engine's encoder writes — one less thing for two ends to disagree about.
//! It is not semantic either way: a scanner parses the object.
use ;
use fields;
/// The reply kind this module reads.
pub const KIND: &str = "enrolled";
/// The marker a scanner recognises the envelope by, and the version of the
/// field set under it.
const MARKER: &str = "yog-enroll";
const VERSION: u64 = 1;
/// The six fields, spelled once. The reader and the envelope both read this
/// list, which is what makes it one list.
const GRADE: &str = "grade";
const NAME: &str = "name";
const ADDRESS: &str = "address";
const CA: &str = "ca";
const CERT: &str = "cert";
const KEY: &str = "key";
/// **What a new box needs to dial this engine, and nothing more.**
///
/// `address` is the engine's own wire address *as clients dial it*, not the
/// port a `:0` request became — REMOTE §8.4 makes the engine refuse the second,
/// because a symbol carrying a runtime port would be stale before it was
/// scanned. So a seat has nothing to check here: an address that arrived is an
/// address the engine already stood behind.
/// Read the material. **Rung 1 throughout**: every field is required and every
/// refusal names the field, because a half-read enrollment is a symbol that
/// scans into a box that cannot dial.
pub