1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct SigningCeremonySpec {
8 pub scheme: String,
10 pub threshold: u32,
12 #[serde(rename = "partyCount")]
14 pub party_count: u32,
15 #[serde(rename = "messageRef")]
17 pub message_ref: ConfigMapRef,
18 #[serde(rename = "outputRef")]
20 pub output_ref: SecretRef,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct ConfigMapRef {
26 pub config_map: String,
27 pub key: String,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct SecretRef {
33 pub secret: String,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct SigningCeremonyStatus {
39 pub phase: CeremonyPhase,
40 pub started_at: Option<String>,
41 pub completed_at: Option<String>,
42 pub signature_secret: Option<String>,
43 pub error: Option<String>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
48#[serde(rename_all = "lowercase")]
49pub enum CeremonyPhase {
50 Pending,
52 KeygenRunning,
54 Signing,
56 Completed,
58 Failed,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct SigningCeremony {
65 #[serde(rename = "apiVersion")]
66 pub api_version: String,
67 pub kind: String,
68 pub metadata: ObjectMeta,
69 pub spec: SigningCeremonySpec,
70 pub status: Option<SigningCeremonyStatus>,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct ObjectMeta {
76 pub name: String,
77 pub namespace: Option<String>,
78 #[serde(default)]
79 pub labels: std::collections::BTreeMap<String, String>,
80}
81
82pub fn crd_yaml() -> String {
84 r#"apiVersion: apiextensions.k8s.io/v1
85kind: CustomResourceDefinition
86metadata:
87 name: confiumsigningceremonies.confium.org
88spec:
89 group: confium.org
90 names:
91 kind: ConfiumSigningCeremony
92 listKind: ConfiumSigningCeremonyList
93 plural: confiumsigningceremonies
94 singular: confiumsigningceremony
95 scope: Namespaced
96 versions:
97 - name: v1alpha1
98 served: true
99 storage: true
100 schema:
101 openAPIV3Schema:
102 type: object
103 properties:
104 spec:
105 type: object
106 required: [scheme, threshold, partyCount]
107 properties:
108 scheme:
109 type: string
110 enum: [cmp20, gg18]
111 threshold:
112 type: integer
113 minimum: 1
114 partyCount:
115 type: integer
116 minimum: 1
117 messageRef:
118 type: object
119 properties:
120 configMap: { type: string }
121 key: { type: string }
122 outputRef:
123 type: object
124 properties:
125 secret: { type: string }
126 status:
127 type: object
128 properties:
129 phase:
130 type: string
131 enum: [pending, keygenrunning, signing, completed, failed]
132 startedAt: { type: string }
133 completedAt: { type: string }
134 signatureSecret: { type: string }
135 error: { type: string }
136"#
137 .to_string()
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn crd_yaml_is_valid_yaml() {
146 let yaml = crd_yaml();
147 let parsed: serde_yaml::Value = serde_yaml::from_str(&yaml).expect("CRD YAML must parse");
148 assert_eq!(parsed["kind"], "CustomResourceDefinition");
149 }
150
151 #[test]
152 fn ceremony_spec_round_trips() {
153 let spec = SigningCeremonySpec {
154 scheme: "cmp20".to_string(),
155 threshold: 3,
156 party_count: 5,
157 message_ref: ConfigMapRef {
158 config_map: "release-artifact".to_string(),
159 key: "release.tar.gz".to_string(),
160 },
161 output_ref: SecretRef {
162 secret: "release-signature".to_string(),
163 },
164 };
165 let json = serde_json::to_string(&spec).unwrap();
166 let parsed: SigningCeremonySpec = serde_json::from_str(&json).unwrap();
167 assert_eq!(parsed.scheme, "cmp20");
168 assert_eq!(parsed.threshold, 3);
169 }
170}