gunnar-server 2.0.0

The gunnar git server: SSH and smart-HTTP git transports and the gRPC control plane. The appliance half, extracted from gunnar-cli so the server code lives in its own crate.
Documentation
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
//! **The go-ahead** — the signed fact a growth is started on (D3, T14 in
//! `DATA-SET-GROWTH-FLOW.md`).
//!
//! gunnar never dials monetize (the shop-presence contract), so whatever
//! approves a growth — an operator at the CLI, monetize after its € gate —
//! reaches gunnar as bytes on `Admin.GrowStart`. gunnar verifies the
//! STRUCTURE here, once, and hands the WHO to a pluggable
//! [`GoAheadPolicy`]:
//!
//! ```text
//!   {
//!     "v": 1,
//!     "signer": "operator" | "monetize",
//!     "target_sectors": <u64>,          // must equal the request's
//!     "nonce": "<opaque, non-empty>",   // spent once per box (the ledger beside the journal)
//!     "issued_unix_ms": <i64>,          // the policy bounds its age
//!     "signature": "<base64>"           // whatever the signer's policy verifies; may be empty
//!   }
//! ```
//!
//! [`OperatorPolicy`] is the default and accepts an `operator` go-ahead
//! without a signature — the RPC that carries it is already gunnar-admin,
//! which is the second column of D3 (the cap is checked by whoever calls
//! `Start`). A `monetize` go-ahead is REFUSED by it: a metered build plugs
//! [`MonetizePolicy`], which verifies `signature` under monetize's Ed25519 key
//! over the canonical bytes (the same `monetize_embed::signing` pair the
//! entitlement facts use), through
//! [`GrowMachine::with_policy`](super::GrowMachine::with_policy).
//! The structure and the nonce ledger are shared by every policy, so the
//! replay and the target check cannot be forgotten by one of them.
//!
//! # That plug did not exist until 2026-09-18, and front-driven growth was dead on it
//!
//! AUDITED 2026-09-18: the paragraph above was a description of intent.
//! `serve.rs` built the machine with `GrowMachine::new`, which installs
//! [`OperatorPolicy`], and nothing anywhere implemented [`GoAheadPolicy`] for
//! monetize — so monetize's orchestrator reached `phase::STARTING`, called
//! `Admin.GrowStart` with its own signed go-ahead and was refused by name,
//! AFTER it had reserved the spend and flushed. [`MonetizePolicy`] is that
//! missing half. It is `cfg(feature = "metered")`, like every other line of
//! the money half (`crate::entitlement`, `Entitlement`/`Billing` in
//! `gunnar_grpc`): the community binary contains no monetize verifier at all,
//! which a symbol table is the proof of, and its behaviour is untouched.

use serde::Deserialize;

/// The oldest go-ahead the operator policy takes, ms. A stale one is a
/// script re-run by mistake, not an approval.
pub const MAX_GO_AHEAD_AGE_MS: i64 = 24 * 3600 * 1000;

/// A go-ahead, parsed.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct GoAhead {
    pub v: u32,
    pub signer: String,
    pub target_sectors: u64,
    pub nonce: String,
    pub issued_unix_ms: i64,
    #[serde(default)]
    pub signature: String,
    /// ★ **Non-empty: grow WITHOUT a caught-up standby, and why** (cov-13, 2026-10-06) —
    /// the approver's EMERGENCY (monetize's ALERT words: the set at ≥ 90 % and the twin
    /// silent past its bound or not catching up under load). The drain still looks, and
    /// a standby that is behind is said instead of obeyed.
    ///
    /// OUTSIDE the signature: `monetize_embed::signing::go_ahead_message` covers the six
    /// fields above and [`MonetizePolicy`] re-encodes exactly those, so this key changes
    /// nothing that is verified. That is acceptable for what it is: it relaxes a SAFETY
    /// precondition (ruling 2's re-lay needs a current twin), never money, and it arrives
    /// on `Admin.GrowStart`, a gunnar-admin call.
    #[serde(default)]
    pub alone: String,
}

impl GoAhead {
    /// Parse and check the structure: version 1, a known signer, a
    /// non-empty nonce. Everything else is the policy's.
    pub fn parse(bytes: &[u8]) -> Result<GoAhead, String> {
        if bytes.is_empty() {
            return Err("the go-ahead is empty".into());
        }
        let go: GoAhead = serde_json::from_slice(bytes).map_err(|e| format!("the go-ahead is not the JSON object this box expects ({e}); see gunnar_server::grow::go_ahead"))?;
        if go.v != 1 {
            return Err(format!("go-ahead version {} is not 1", go.v));
        }
        if !matches!(go.signer.as_str(), "operator" | "monetize") {
            return Err(format!("go-ahead signer {:?} is neither `operator` nor `monetize`", go.signer));
        }
        if go.nonce.trim().is_empty() || go.nonce.len() > 256 || go.nonce.contains(['\n', '\r']) {
            return Err("go-ahead nonce must be one non-empty line of at most 256 bytes".into());
        }
        Ok(go)
    }

    /// The bytes an operator go-ahead is minted as (`gunnar control grow start`).
    pub fn operator(target_sectors: u64, nonce: &str, issued_unix_ms: i64) -> Vec<u8> {
        serde_json::to_vec(&serde_json::json!({
            "v": 1,
            "signer": "operator",
            "target_sectors": target_sectors,
            "nonce": nonce,
            "issued_unix_ms": issued_unix_ms,
            "signature": "",
        }))
        .expect("a JSON object of scalars encodes")
    }
}

/// **Who may say go.** Pluggable; see the module docs.
pub trait GoAheadPolicy: Send + Sync + 'static {
    /// Accept or refuse, by name.
    fn verify(&self, go: &GoAhead, now_unix_ms: i64) -> Result<(), String>;
    /// For the log.
    fn name(&self) -> &'static str;
}

/// The default: an `operator` go-ahead carried on a gunnar-admin RPC is the
/// approval; `monetize` is refused until a policy that can verify it is
/// plugged in.
#[derive(Debug, Clone)]
pub struct OperatorPolicy {
    pub max_age_ms: i64,
}

impl Default for OperatorPolicy {
    fn default() -> Self {
        OperatorPolicy { max_age_ms: MAX_GO_AHEAD_AGE_MS }
    }
}

impl GoAheadPolicy for OperatorPolicy {
    fn verify(&self, go: &GoAhead, now_unix_ms: i64) -> Result<(), String> {
        match go.signer.as_str() {
            "operator" => {}
            other => {
                return Err(format!(
                    "a `{other}` go-ahead cannot be verified by this box: no policy for that signer is plugged in (the default policy takes `operator` go-aheads on a gunnar-admin call)"
                ))
            }
        }
        bound_age(go, now_unix_ms, self.max_age_ms)
    }
    fn name(&self) -> &'static str {
        "operator"
    }
}

/// **The age window, one implementation.** Whoever signed it, a go-ahead is an
/// approval of a growth NOW: too old is a script re-run by mistake, and dated
/// ahead is a clock nobody has looked at. Lifted out of [`OperatorPolicy`]
/// unchanged (same two sentences, same numbers) when [`MonetizePolicy`] was
/// added, so the two policies cannot drift into two different windows — the
/// way `fact_message` is one canonical form for both halves of the
/// entitlement path.
fn bound_age(go: &GoAhead, now_unix_ms: i64, max_age_ms: i64) -> Result<(), String> {
    let age = now_unix_ms - go.issued_unix_ms;
    if age > max_age_ms {
        return Err(format!("the go-ahead was issued {} s ago, past the {} s ceiling; mint a fresh one", age / 1000, max_age_ms / 1000));
    }
    if age < -5 * 60 * 1000 {
        return Err(format!("the go-ahead is dated {} s in the future; whose clock is wrong?", -age / 1000));
    }
    Ok(())
}

/// **The metered appliance's policy: monetize's Ed25519 signature, under the
/// key the box was already installed with.** `metered` only — see the module
/// docs for the audit that found this half missing.
///
/// # Where the key comes from: the one the box already holds
///
/// No new config knob. A metered gunnar is started with `--monetize-pubkey`
/// (`gunnar_common::cli::ServeArgs`, 64 hex inline or a file — inline on the
/// appliance, whose only writable channel is the kernel cmdline), it is
/// resolved once into [`crate::entitlement::MeteredConfig::monetize_pubkey`],
/// and the same 32 bytes already verify every `EntitlementFact` that reaches
/// `Entitlement.Set`. monetize signs the go-ahead with the SAME signing key it
/// signs facts with (`monetize::sign::Signer::sign_go_ahead`), and
/// `monetize_embed::signing` documents that pairing in the doc comment on its
/// own `GoAhead` — so a box that can be billed can, by construction, check who
/// told it to grow. A second key would have to be distributed, rotated and
/// kept in step with the first, and a box that had only one of the two would
/// be a support ticket nobody can read off the console.
///
/// # An `operator` go-ahead is still taken, and that is not a weakening
///
/// This policy delegates `operator` to an [`OperatorPolicy`] it owns rather
/// than refusing it. `Admin.GrowStart` is a gunnar-admin RPC on every build,
/// so the operator arm here is exactly the door a metered box has today; the
/// hosted tenant does not hold that capability and never reaches it. Refusing
/// it instead would take away the owner's own way to grow a metered appliance
/// when monetize is unreachable — a capability removed, not a hole closed.
#[cfg(feature = "metered")]
pub struct MonetizePolicy {
    /// `None` while the key is AWAITED (the installer feeds it): a `monetize`
    /// go-ahead is refused by name until [`MonetizePolicy::set_key`] applies it
    /// in place — no restart (owner 2026-09-25).
    key: std::sync::RwLock<Option<monetize_embed::VerifyingKey>>,
    /// The `operator` arm, unchanged; see the type docs.
    operator: OperatorPolicy,
    pub max_age_ms: i64,
}

#[cfg(feature = "metered")]
impl std::fmt::Debug for MonetizePolicy {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("MonetizePolicy").field("max_age_ms", &self.max_age_ms).finish()
    }
}

#[cfg(feature = "metered")]
impl MonetizePolicy {
    /// Over the 32 bytes `--monetize-pubkey` resolved to. Refuses at BOOT if
    /// they are not a point on the curve, in the same voice as
    /// `EntitlementSlot::open`: a metered box whose growth door could never
    /// open must say so while somebody is watching the console, not on the
    /// first growth six months later.
    pub fn new(monetize_pubkey: &[u8; 32]) -> Result<Self, String> {
        let key = monetize_embed::VerifyingKey::from_bytes(monetize_pubkey)
            .map_err(|e| format!("the monetize public key this box was started with is not a valid Ed25519 point ({e}); no `monetize` go-ahead could ever verify under it"))?;
        Ok(MonetizePolicy { key: std::sync::RwLock::new(Some(key)), operator: OperatorPolicy::default(), max_age_ms: MAX_GO_AHEAD_AGE_MS })
    }

    /// A metered box whose monetize key the installer feeds and has not yet:
    /// the `operator` door as always, `monetize` refused by name until the key
    /// arrives.
    pub fn awaiting() -> Self {
        MonetizePolicy { key: std::sync::RwLock::new(None), operator: OperatorPolicy::default(), max_age_ms: MAX_GO_AHEAD_AGE_MS }
    }

    /// **The key, applied in place** when it arrives while running.
    pub fn set_key(&self, monetize_pubkey: &[u8; 32]) -> Result<(), String> {
        let key = monetize_embed::VerifyingKey::from_bytes(monetize_pubkey)
            .map_err(|e| format!("the fed monetize public key is not a valid Ed25519 point ({e})"))?;
        *self.key.write().unwrap_or_else(|p| p.into_inner()) = Some(key);
        Ok(())
    }
}

#[cfg(feature = "metered")]
impl GoAheadPolicy for MonetizePolicy {
    fn verify(&self, go: &GoAhead, now_unix_ms: i64) -> Result<(), String> {
        match go.signer.as_str() {
            "operator" => return self.operator.verify(go, now_unix_ms),
            "monetize" => {}
            other => {
                // `GoAhead::parse` has already refused anything but these two
                // words, so this arm is reached only by a caller holding the
                // struct directly. It refuses by name rather than falling
                // through to a signature check that would be meaningless.
                return Err(format!("go-ahead signer {other:?} is neither `operator` nor `monetize`; this box verifies a `monetize` signature and takes an `operator` go-ahead on a gunnar-admin call, and nothing else"));
            }
        }
        bound_age(go, now_unix_ms, self.max_age_ms)?;
        // The signature covers `monetize_embed::signing::go_ahead_message` —
        // the canonical JSON of the six fields MINUS `signature`. gunnar parsed
        // the wire bytes once, into its own `GoAhead` (the structure check every
        // policy shares), so the same six fields are handed back to
        // monetize-embed's own verifier here instead of a canonicaliser being
        // written a second time in this crate: the sorted-key form is a
        // function of the values, so the round trip through serde cannot change
        // what is checked, and there is no second encoding for a forger to aim
        // at (the argument `crate::entitlement`'s module docs make about
        // `verify_fact`).
        let wire = monetize_embed::signing::GoAhead {
            v: go.v,
            signer: go.signer.clone(),
            target_sectors: go.target_sectors,
            nonce: go.nonce.clone(),
            issued_unix_ms: go.issued_unix_ms,
            signature: go.signature.clone(),
        };
        let bytes = serde_json::to_vec(&wire).expect("a go-ahead of scalars encodes");
        let key = self.key.read().unwrap_or_else(|p| p.into_inner()).clone().ok_or_else(|| {
            format!("the `monetize` go-ahead for nonce {:?} cannot be checked: this box has no monetize key yet (the installer feeds it)", go.nonce)
        })?;
        monetize_embed::signing::verify_go_ahead(&bytes, &key).map(|_| ()).map_err(|e| {
            format!(
                "the `monetize` go-ahead for nonce {:?} does not verify under the monetize public key this box was started with ({e}); it was not signed by the monetize this appliance was installed against, or it was altered on the way",
                go.nonce
            )
        })
    }
    fn name(&self) -> &'static str {
        "monetize"
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    /// The structure is checked once, for every policy: version, signer,
    /// nonce, target — and the operator policy's age window.
    #[test]
    fn a_go_ahead_is_parsed_strictly_and_the_operator_policy_bounds_its_age() {
        let now = 1_800_000_000_000;
        let ok = GoAhead::operator(4096, "n-1", now - 1000);
        let go = GoAhead::parse(&ok).expect("parses");
        assert_eq!((go.v, go.signer.as_str(), go.target_sectors, go.nonce.as_str()), (1, "operator", 4096, "n-1"));
        let p = OperatorPolicy::default();
        p.verify(&go, now).expect("fresh operator go-ahead");

        assert!(GoAhead::parse(b"").unwrap_err().contains("empty"));
        assert!(GoAhead::parse(b"not json").unwrap_err().contains("not the JSON"));
        assert!(GoAhead::parse(br#"{"v":2,"signer":"operator","target_sectors":1,"nonce":"x","issued_unix_ms":1}"#).unwrap_err().contains("version"));
        assert!(GoAhead::parse(br#"{"v":1,"signer":"root","target_sectors":1,"nonce":"x","issued_unix_ms":1}"#).unwrap_err().contains("signer"));
        assert!(GoAhead::parse(br#"{"v":1,"signer":"operator","target_sectors":1,"nonce":"","issued_unix_ms":1}"#).unwrap_err().contains("nonce"));
        assert!(GoAhead::parse(br#"{"v":1,"signer":"operator","target_sectors":1,"nonce":"a\nb","issued_unix_ms":1}"#).unwrap_err().contains("nonce"));

        let stale = GoAhead::parse(&GoAhead::operator(1, "n-2", now - MAX_GO_AHEAD_AGE_MS - 1)).unwrap();
        assert!(p.verify(&stale, now).unwrap_err().contains("past the"));
        let future = GoAhead::parse(&GoAhead::operator(1, "n-3", now + 10 * 60 * 1000)).unwrap();
        assert!(p.verify(&future, now).unwrap_err().contains("future"));
        let monetize = GoAhead::parse(br#"{"v":1,"signer":"monetize","target_sectors":1,"nonce":"m","issued_unix_ms":1,"signature":"AAAA"}"#).unwrap();
        assert!(p.verify(&monetize, now).unwrap_err().contains("no policy for that signer"));
    }
}

/// The metered half's policy. `monetize-embed` and `ed25519-dalek` are
/// unconditional dev-dependencies of this crate, so these sign a go-ahead the
/// way `monetize::sign::Signer::sign_go_ahead` does — over
/// `monetize_embed::signing::go_ahead_message`, the ONE canonical form —
/// rather than against a stand-in of gunnar's own (the argument
/// `tests/entitlement.rs` makes for facts).
#[cfg(all(test, feature = "metered"))]
pub(super) mod metered_tests {
    use super::*;
    use ed25519_dalek::{Signer as _, SigningKey};
    use monetize_embed::signing::{base64_encode, go_ahead_message, GO_AHEAD_SIGNER_MONETIZE};

    fn key(seed: u8) -> SigningKey {
        SigningKey::from_bytes(&[seed; 32])
    }

    /// Exactly what monetize puts on the wire.
    pub(crate) fn signed(k: &SigningKey, target_sectors: u64, nonce: &str, issued_unix_ms: i64) -> Vec<u8> {
        let mut go = monetize_embed::signing::GoAhead {
            v: 1,
            signer: GO_AHEAD_SIGNER_MONETIZE.into(),
            target_sectors,
            nonce: nonce.into(),
            issued_unix_ms,
            signature: String::new(),
        };
        go.signature = base64_encode(&k.sign(&go_ahead_message(&go)).to_bytes());
        serde_json::to_vec(&go).expect("encodes")
    }

    /// **The half the 2026-09-18 audit found missing**: a go-ahead monetize
    /// signed verifies under the box's `--monetize-pubkey`, and a signature
    /// that is forged, moved, tampered with or simply absent is refused BY
    /// NAME — never silently taken.
    #[test]
    fn a_monetize_signed_go_ahead_verifies_and_a_bad_signature_is_refused_by_name() {
        let now = 1_800_000_000_000;
        let monetize = key(7);
        let p = MonetizePolicy::new(&monetize.verifying_key().to_bytes()).expect("a real key");
        assert_eq!(p.name(), "monetize");

        let go = GoAhead::parse(&signed(&monetize, 4096, "m-1", now - 1000)).expect("parses");
        assert_eq!((go.signer.as_str(), go.target_sectors), ("monetize", 4096));
        p.verify(&go, now).expect("monetize's own signature verifies");

        // Signed by somebody else's key: the box was installed against ONE monetize.
        let impostor = GoAhead::parse(&signed(&key(9), 4096, "m-2", now - 1000)).unwrap();
        let err = p.verify(&impostor, now).unwrap_err();
        assert!(err.contains("does not verify") && err.contains("m-2"), "{err}");

        // A field changed after signing: the signature covers all six.
        let mut tampered = go.clone();
        tampered.target_sectors = 8192;
        assert!(p.verify(&tampered, now).unwrap_err().contains("does not verify"));
        let mut moved = go.clone();
        moved.nonce = "m-3".into();
        assert!(p.verify(&moved, now).unwrap_err().contains("does not verify"));

        // No signature at all — the shape an `operator` go-ahead has, worn by
        // a `monetize` one. It is not waved through.
        let mut bare = go.clone();
        bare.signature = String::new();
        assert!(p.verify(&bare, now).unwrap_err().contains("does not verify"));
        let mut junk = go.clone();
        junk.signature = "!!!not base64!!!".into();
        assert!(p.verify(&junk, now).unwrap_err().contains("does not verify"));

        // The age window is the same one, and it is checked before the key.
        let stale = GoAhead::parse(&signed(&monetize, 4096, "m-4", now - MAX_GO_AHEAD_AGE_MS - 1)).unwrap();
        assert!(p.verify(&stale, now).unwrap_err().contains("past the"));
        let ahead = GoAhead::parse(&signed(&monetize, 4096, "m-5", now + 10 * 60 * 1000)).unwrap();
        assert!(p.verify(&ahead, now).unwrap_err().contains("future"));
    }

    /// **A wrong signer is refused by name at both doors**, and neither door
    /// was moved: the metered policy still takes the operator's go-ahead
    /// (`Admin.GrowStart` is gunnar-admin on every build), and
    /// [`OperatorPolicy`] still refuses monetize — nothing about the community
    /// build changed.
    #[test]
    fn a_wrong_signer_is_refused_by_name_and_neither_the_operator_nor_the_community_door_moved() {
        let now = 1_800_000_000_000;
        let monetize = key(7);
        let p = MonetizePolicy::new(&monetize.verifying_key().to_bytes()).unwrap();

        // A third word never gets as far as a signature check.
        let err = GoAhead::parse(br#"{"v":1,"signer":"root","target_sectors":1,"nonce":"x","issued_unix_ms":1,"signature":"AAAA"}"#).unwrap_err();
        assert!(err.contains("signer") && err.contains("root"), "{err}");
        let held = GoAhead { v: 1, signer: "root".into(), target_sectors: 1, nonce: "x".into(), issued_unix_ms: now, signature: String::new(), alone: String::new() };
        assert!(p.verify(&held, now).unwrap_err().contains("neither `operator` nor `monetize`"));

        // The operator arm, unchanged, under the metered policy…
        let op = GoAhead::parse(&GoAhead::operator(4096, "op-1", now - 1000)).unwrap();
        p.verify(&op, now).expect("a metered box still takes its owner's go-ahead");
        assert!(p.verify(&GoAhead::parse(&GoAhead::operator(1, "op-2", 1)).unwrap(), now).unwrap_err().contains("past the"));

        // …and the community policy, which has no key and says so.
        let mon = GoAhead::parse(&signed(&monetize, 4096, "m-9", now - 1000)).unwrap();
        let err = OperatorPolicy::default().verify(&mon, now).unwrap_err();
        assert!(err.contains("no policy for that signer"), "{err}");

        // A key that is not a point on the curve is a BOOT refusal, not a
        // growth-time surprise. `[0xdd; 32]` is one such encoding (measured
        // against ed25519-dalek 2 by scanning every repeated byte; `[0xff; 32]`
        // is NOT — dalek masks the sign bit and reduces, so the all-ones
        // spelling decompresses, and a "clearly wrong" key is not the same
        // thing as an invalid one).
        assert!(MonetizePolicy::new(&[0xdd; 32]).unwrap_err().contains("not a valid Ed25519 point"));
    }

    /// **The fed key applies in place** (owner 2026-09-25: avoid restarts): a
    /// policy built before the key arrived refuses a `monetize` go-ahead by
    /// name, keeps the operator door, and once the key is set the SAME policy
    /// accepts a go-ahead signed with it — no restart.
    #[cfg(feature = "metered")]
    #[test]
    fn a_go_ahead_signed_with_a_key_fed_while_running_is_accepted_by_the_same_policy() {
        let now = 1_800_000_000_000;
        let monetize = key(7);
        let p = MonetizePolicy::awaiting();
        let go = GoAhead::parse(&signed(&monetize, 4096, "m-live", now - 1000)).unwrap();
        assert!(p.verify(&go, now).unwrap_err().contains("no monetize key yet"));
        p.verify(&GoAhead::parse(&GoAhead::operator(4096, "op-live", now - 1000)).unwrap(), now).expect("the operator door is there keyless");
        p.set_key(&monetize.verifying_key().to_bytes()).unwrap();
        p.verify(&go, now).expect("the same policy, the fed key, no restart");
        let impostor = GoAhead::parse(&signed(&key(9), 4096, "m-other", now - 1000)).unwrap();
        assert!(p.verify(&impostor, now).unwrap_err().contains("does not verify"));
        assert!(p.set_key(&[0xdd; 32]).unwrap_err().contains("not a valid Ed25519 point"));
    }
}