nixfleet_proto/
enroll_wire.rs

1//! Bootstrap token + enrollment + renewal wire types. Tokens carry a detached
2//! ed25519 signature over JCS-canonical `claims`, verified against
3//! `orgRootKey.current` from `trust.json`.
4
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
9#[serde(rename_all = "camelCase")]
10pub struct BootstrapToken {
11    /// Consumers MUST refuse unknown versions.
12    pub version: u32,
13    pub claims: TokenClaims,
14    /// Base64 ed25519 signature over JCS-canonical `claims`.
15    pub signature: String,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
19#[serde(rename_all = "camelCase")]
20pub struct TokenClaims {
21    pub hostname: String,
22    /// SHA-256 fingerprint of expected CSR pubkey (base64). Binds the
23    /// token to a specific keypair.
24    pub expected_pubkey_fingerprint: String,
25    pub issued_at: DateTime<Utc>,
26    pub expires_at: DateTime<Utc>,
27    /// Random 16-byte hex nonce. Backs replay detection.
28    pub nonce: String,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct EnrollRequest {
34    pub token: BootstrapToken,
35    /// PEM CSR. CP validates CN + pubkey against `token.claims`.
36    pub csr_pem: String,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub struct EnrollResponse {
42    pub cert_pem: String,
43    pub not_after: DateTime<Utc>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
47#[serde(rename_all = "camelCase")]
48pub struct RenewRequest {
49    /// PEM CSR. CP validates CN matches mTLS CN and pubkey differs from
50    /// the existing cert's pubkey (rotation is the point of /renew).
51    pub csr_pem: String,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(rename_all = "camelCase")]
56pub struct RenewResponse {
57    pub cert_pem: String,
58    pub not_after: DateTime<Utc>,
59}