vpsnet-mcp 1.0.9 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1621 @@
1
+ import { z } from "zod";
2
+ export const certificateOrderIdSchema = z
3
+ .string()
4
+ .regex(/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/)
5
+ .describe("Customer-owned certificate order UUID returned by list_certificates");
6
+ export const certificateProductIdSchema = z
7
+ .number()
8
+ .int()
9
+ .positive()
10
+ .max(Number.MAX_SAFE_INTEGER)
11
+ .describe("Published product ID returned by list_certificate_catalog");
12
+ export const certificateOfferIdSchema = z
13
+ .number()
14
+ .int()
15
+ .positive()
16
+ .max(Number.MAX_SAFE_INTEGER)
17
+ .describe("Published EUR offer ID returned by the selected catalog product");
18
+ export const certificateOfferGenerationSchema = z
19
+ .number()
20
+ .int()
21
+ .positive()
22
+ .max(Number.MAX_SAFE_INTEGER)
23
+ .describe("Exact offer generation returned by the catalog; stale generations are rejected");
24
+ export const certificateSubscriptionIdSchema = z
25
+ .string()
26
+ .regex(/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/)
27
+ .describe("Customer-owned Automatic SSL subscription UUID returned by list_automatic_ssl_subscriptions");
28
+ export const freeCertificateRequestIdSchema = z
29
+ .string()
30
+ .regex(/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/)
31
+ .describe("Customer-owned free-certificate request UUID returned by list_free_certificates");
32
+ export const freeCertificateStateSchema = z.enum([
33
+ "draft",
34
+ "pending_validation",
35
+ "validating",
36
+ "issuing",
37
+ "issued",
38
+ "renewing",
39
+ "failed",
40
+ "cancelled",
41
+ "revoked",
42
+ "expired",
43
+ ]);
44
+ export const freeCertificateAuthoritySchema = z.enum(["letsencrypt", "zerossl", "google"]);
45
+ export const certificateDnsIdentifierSchema = z
46
+ .string()
47
+ .min(3)
48
+ .max(253)
49
+ .refine((identifier) => {
50
+ if (identifier !== identifier.toLowerCase() || identifier !== identifier.trim()) {
51
+ return false;
52
+ }
53
+ const hostname = identifier.startsWith("*.") ? identifier.slice(2) : identifier;
54
+ const labels = hostname.split(".");
55
+ return labels.length >= 2 && labels.every((label) => /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label));
56
+ }, "Use a canonical lowercase DNS name or a single leading wildcard");
57
+ const certificateAcmeDomainsSchema = z
58
+ .array(certificateDnsIdentifierSchema)
59
+ .min(1)
60
+ .max(255)
61
+ .superRefine((domains, context) => {
62
+ const names = new Set();
63
+ for (const [index, domain] of domains.entries()) {
64
+ if (names.has(domain)) {
65
+ context.addIssue({
66
+ code: z.ZodIssueCode.custom,
67
+ path: [index],
68
+ message: "Automatic SSL DNS names must be unique",
69
+ });
70
+ }
71
+ names.add(domain);
72
+ }
73
+ for (const [index, domain] of domains.entries()) {
74
+ if (domain.startsWith("www.") && names.has(domain.slice(4))) {
75
+ context.addIssue({
76
+ code: z.ZodIssueCode.custom,
77
+ path: [index],
78
+ message: "Do not add www separately when its base domain is subscribed",
79
+ });
80
+ }
81
+ }
82
+ })
83
+ .describe("Canonical subscribed DNS names. A base name includes its www alias; an apex and wildcard are separate names and may be ordered together.");
84
+ export const certificateAcmeSubscriptionInputShape = {
85
+ product_id: certificateProductIdSchema,
86
+ offer_id: certificateOfferIdSchema,
87
+ offer_generation: certificateOfferGenerationSchema,
88
+ auto_renew: z
89
+ .boolean()
90
+ .describe("Explicitly choose whether the subscription remains eligible for separately prepaid future terms"),
91
+ domains: certificateAcmeDomainsSchema,
92
+ };
93
+ export const certificateAcmeSubscriptionDomainInputShape = {
94
+ domain: certificateDnsIdentifierSchema.describe("One canonical DNS name to add. A base name includes www; a wildcard includes its base name."),
95
+ };
96
+ export const certificateAcmeSubscriptionActionRequestSchema = z.discriminatedUnion("action", [
97
+ z.object({
98
+ action: z.literal("cancel"),
99
+ reason: z.string().trim().min(3).max(500),
100
+ }).strict(),
101
+ z.object({
102
+ action: z.literal("remove_domain"),
103
+ domain_id: z.number().int().positive(),
104
+ }).strict(),
105
+ z.object({
106
+ action: z.literal("replace_domain"),
107
+ domain_id: z.number().int().positive(),
108
+ new_domain: certificateDnsIdentifierSchema,
109
+ }).strict(),
110
+ ]);
111
+ export function certificateAcmeSubscriptionActionRequestBody(request) {
112
+ const { action, ...body } = request;
113
+ return { action, body };
114
+ }
115
+ const validationMethodSchema = z
116
+ .string()
117
+ .min(3)
118
+ .max(190)
119
+ .refine((method) => ["dns-txt", "dns-cname", "http", "https"].includes(method)
120
+ || /^(?:admin|administrator|hostmaster|postmaster|webmaster)@[a-z0-9](?:[a-z0-9.-]{1,251}[a-z0-9])$/.test(method), "Use DNS, HTTP/HTTPS, or an allowed administrative mailbox validation method");
121
+ export const certificateIdentifierSchema = z
122
+ .object({
123
+ name: certificateDnsIdentifierSchema,
124
+ validation_method: validationMethodSchema,
125
+ })
126
+ .strict()
127
+ .superRefine((identifier, context) => {
128
+ const hostname = identifier.name.startsWith("*.")
129
+ ? identifier.name.slice(2)
130
+ : identifier.name;
131
+ if (identifier.name.startsWith("*.")
132
+ && !["dns-txt", "dns-cname"].includes(identifier.validation_method)) {
133
+ context.addIssue({
134
+ code: z.ZodIssueCode.custom,
135
+ path: ["validation_method"],
136
+ message: "Wildcard certificates require DNS validation",
137
+ });
138
+ }
139
+ if (identifier.validation_method.includes("@")) {
140
+ const emailDomain = identifier.validation_method.split("@")[1];
141
+ if (emailDomain !== hostname) {
142
+ context.addIssue({
143
+ code: z.ZodIssueCode.custom,
144
+ path: ["validation_method"],
145
+ message: "Administrative validation email must use the exact certificate hostname",
146
+ });
147
+ }
148
+ }
149
+ });
150
+ export const certificateCsrSchema = z
151
+ .string()
152
+ .min(128)
153
+ .max(65536)
154
+ .refine((value) => /^-----BEGIN CERTIFICATE REQUEST-----\n(?:[A-Za-z0-9+/=]+\n)+-----END CERTIFICATE REQUEST-----\n?$/.test(value.replace(/\r\n/g, "\n").trimEnd() + "\n") && !value.includes("PRIVATE KEY"), "Provide only a PEM PKCS#10 certificate signing request; never provide a private key")
155
+ .describe("Customer-generated PEM PKCS#10 CSR. The private key must remain with the customer and must never be sent to VPSnet or an AI assistant.");
156
+ const freeCertificateAlternativeNamesSchema = z
157
+ .array(certificateDnsIdentifierSchema)
158
+ .max(99)
159
+ .superRefine((identifiers, context) => {
160
+ const seen = new Set();
161
+ for (const [index, identifier] of identifiers.entries()) {
162
+ if (seen.has(identifier)) {
163
+ context.addIssue({
164
+ code: z.ZodIssueCode.custom,
165
+ path: [index],
166
+ message: "Free-certificate DNS names must be unique",
167
+ });
168
+ }
169
+ seen.add(identifier);
170
+ }
171
+ })
172
+ .default([])
173
+ .describe("Optional unique lowercase DNS subject alternative names");
174
+ const freeCertificateTargetOrderIdSchema = z
175
+ .number()
176
+ .int()
177
+ .positive()
178
+ .max(Number.MAX_SAFE_INTEGER)
179
+ .nullable()
180
+ .optional()
181
+ .describe("Optional owned VPS or Cloud VPS order ID returned by service tools");
182
+ export const freeCertificatePreflightInputShape = {
183
+ hostname: certificateDnsIdentifierSchema.describe("Primary lowercase DNS name; wildcards begin with *."),
184
+ alternative_names: freeCertificateAlternativeNamesSchema,
185
+ target_order_id: freeCertificateTargetOrderIdSchema,
186
+ certificate_authority: freeCertificateAuthoritySchema
187
+ .nullable()
188
+ .optional()
189
+ .describe("Optional CA choice; omit to let preflight recommend a currently ready authority"),
190
+ };
191
+ export const freeCertificatePreflightRequestSchema = z
192
+ .object(freeCertificatePreflightInputShape)
193
+ .strict()
194
+ .superRefine((request, context) => {
195
+ if (request.alternative_names.includes(request.hostname)) {
196
+ context.addIssue({
197
+ code: z.ZodIssueCode.custom,
198
+ path: ["alternative_names"],
199
+ message: "Do not repeat the primary hostname as an alternative name",
200
+ });
201
+ }
202
+ });
203
+ export const freeCertificateCreateInputShape = {
204
+ ...freeCertificatePreflightInputShape,
205
+ key_mode: z.enum(["managed", "customer_csr"]).describe("managed enables unattended renewal but its private key stays portal/2FA-only; customer_csr keeps the private key with the caller"),
206
+ csr: certificateCsrSchema
207
+ .nullable()
208
+ .optional()
209
+ .describe("Required only for customer_csr. Supply a public PKCS#10 CSR, never a private key"),
210
+ validation_method: z.enum(["dns_zone", "dns_cname"]).describe("Choose only a validation method that preflight reports available"),
211
+ delivery_method: z.enum(["download", "auto_install_guest", "assistant_install"]).describe("Choose only a delivery method that preflight reports available"),
212
+ };
213
+ export const freeCertificateCreateRequestSchema = z
214
+ .object(freeCertificateCreateInputShape)
215
+ .strict()
216
+ .superRefine((request, context) => {
217
+ if (request.alternative_names.includes(request.hostname)) {
218
+ context.addIssue({
219
+ code: z.ZodIssueCode.custom,
220
+ path: ["alternative_names"],
221
+ message: "Do not repeat the primary hostname as an alternative name",
222
+ });
223
+ }
224
+ if (request.key_mode === "customer_csr" && !request.csr) {
225
+ context.addIssue({
226
+ code: z.ZodIssueCode.custom,
227
+ path: ["csr"],
228
+ message: "customer_csr mode requires a public PKCS#10 CSR",
229
+ });
230
+ }
231
+ if (request.key_mode === "managed" && request.csr != null) {
232
+ context.addIssue({
233
+ code: z.ZodIssueCode.custom,
234
+ path: ["csr"],
235
+ message: "Managed mode does not accept a CSR",
236
+ });
237
+ }
238
+ });
239
+ export const freeCertificateActionRequestSchema = z.discriminatedUnion("action", [
240
+ z.object({
241
+ action: z.literal("renew"),
242
+ csr: certificateCsrSchema.nullable().optional(),
243
+ }).strict(),
244
+ z.object({
245
+ action: z.literal("revoke"),
246
+ reason: z.enum(["unspecified", "key_compromise", "superseded", "cessation_of_operation"]),
247
+ }).strict(),
248
+ z.object({ action: z.literal("recheck") }).strict(),
249
+ z.object({ action: z.literal("cancel") }).strict(),
250
+ ]);
251
+ export function freeCertificateActionRequestBody(request) {
252
+ const { action, ...body } = request;
253
+ return { action, body };
254
+ }
255
+ export const certificateOrderInputShape = {
256
+ product_id: certificateProductIdSchema,
257
+ offer_id: certificateOfferIdSchema,
258
+ offer_generation: certificateOfferGenerationSchema,
259
+ common_name: certificateIdentifierSchema.describe("Primary certificate name and its validation method"),
260
+ alternative_names: z
261
+ .array(certificateIdentifierSchema)
262
+ .max(100)
263
+ .default([])
264
+ .describe("Optional unique subject alternative names; pricing is returned by quote_certificate"),
265
+ csr: certificateCsrSchema,
266
+ administrator_contact_id: z
267
+ .number()
268
+ .int()
269
+ .positive()
270
+ .max(Number.MAX_SAFE_INTEGER)
271
+ .describe("Owned administrator contact ID selected in the VPSnet certificate order form"),
272
+ technical_contact_id: z
273
+ .number()
274
+ .int()
275
+ .positive()
276
+ .max(Number.MAX_SAFE_INTEGER)
277
+ .describe("Owned technical contact ID selected in the VPSnet certificate order form"),
278
+ organization_contact_id: z
279
+ .number()
280
+ .int()
281
+ .positive()
282
+ .max(Number.MAX_SAFE_INTEGER)
283
+ .nullable()
284
+ .optional()
285
+ .describe("Owned organization contact ID when required for OV or EV validation"),
286
+ renewal_of: certificateOrderIdSchema
287
+ .nullable()
288
+ .optional()
289
+ .describe("Existing eligible certificate order UUID when quoting a renewal"),
290
+ };
291
+ export const certificateActionRequestSchema = z.discriminatedUnion("action", [
292
+ z.object({
293
+ action: z.literal("cancel"),
294
+ reason: z.string().min(3).max(500),
295
+ }).strict(),
296
+ z.object({
297
+ action: z.literal("recheck_validation"),
298
+ domains: z.array(certificateDnsIdentifierSchema).min(1).max(100),
299
+ }).strict(),
300
+ z.object({ action: z.literal("resend_validation") }).strict(),
301
+ z.object({
302
+ action: z.literal("change_validation"),
303
+ domain: certificateDnsIdentifierSchema,
304
+ validation_method: validationMethodSchema,
305
+ }).strict(),
306
+ z.object({
307
+ action: z.literal("reissue"),
308
+ csr: certificateCsrSchema,
309
+ common_name: certificateIdentifierSchema,
310
+ alternative_names: z.array(certificateIdentifierSchema).max(99).default([]),
311
+ }).strict(),
312
+ ]);
313
+ export function certificateActionRequestBody(request) {
314
+ const { action, ...body } = request;
315
+ return { action, body };
316
+ }
317
+ function record(value) {
318
+ return value !== null && typeof value === "object" && !Array.isArray(value)
319
+ ? value
320
+ : {};
321
+ }
322
+ function text(value, maximum = 1024) {
323
+ if (typeof value !== "string" || value.length > maximum || value.includes("\0")) {
324
+ return null;
325
+ }
326
+ return value;
327
+ }
328
+ function integer(value) {
329
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0
330
+ ? value
331
+ : null;
332
+ }
333
+ function nonNegativeInteger(value) {
334
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0
335
+ ? value
336
+ : null;
337
+ }
338
+ function nullableInteger(value) {
339
+ return value === null ? null : integer(value);
340
+ }
341
+ function boolean(value) {
342
+ return value === true;
343
+ }
344
+ function timestamp(value) {
345
+ return value === null ? null : text(value, 64);
346
+ }
347
+ function money(value) {
348
+ return typeof value === "string" && /^(?:0|[1-9][0-9]*)(?:\.[0-9]{1,4})?$/.test(value)
349
+ ? value
350
+ : null;
351
+ }
352
+ function safeIdentifier(value) {
353
+ const source = record(value);
354
+ const parsed = certificateIdentifierSchema.safeParse(source);
355
+ return parsed.success ? parsed.data : null;
356
+ }
357
+ function safeOffer(value) {
358
+ const source = record(value);
359
+ const id = integer(source.id);
360
+ const generation = integer(source.generation);
361
+ const termMonths = integer(source.term_months);
362
+ const nameKind = source.name_kind === "single" || source.name_kind === "wildcard"
363
+ ? source.name_kind
364
+ : null;
365
+ const basePrice = money(source.base_price);
366
+ const singlePrice = source.san_single_price === null ? null : money(source.san_single_price);
367
+ const wildcardPrice = source.san_wildcard_price === null ? null : money(source.san_wildcard_price);
368
+ if (id === null
369
+ || generation === null
370
+ || termMonths === null
371
+ || nameKind === null
372
+ || source.currency !== "EUR"
373
+ || basePrice === null
374
+ || (source.san_single_price !== null && singlePrice === null)
375
+ || (source.san_wildcard_price !== null && wildcardPrice === null)) {
376
+ return null;
377
+ }
378
+ return {
379
+ id,
380
+ generation,
381
+ term_months: termMonths,
382
+ name_kind: nameKind,
383
+ currency: "EUR",
384
+ base_price: basePrice,
385
+ san_single_price: singlePrice,
386
+ san_wildcard_price: wildcardPrice,
387
+ };
388
+ }
389
+ function safeProduct(value) {
390
+ const source = record(value);
391
+ const id = integer(source.id);
392
+ const label = text(source.label, 255);
393
+ const category = source.category === "caas" || source.category === "tls"
394
+ ? source.category
395
+ : null;
396
+ const fulfillment = source.fulfillment === "acme_subscription"
397
+ || source.fulfillment === "portable_certificate"
398
+ ? source.fulfillment
399
+ : null;
400
+ const validationType = ["DV", "OV", "EV"].includes(String(source.validation_type))
401
+ ? String(source.validation_type)
402
+ : null;
403
+ if (id === null
404
+ || label === null
405
+ || category === null
406
+ || fulfillment === null
407
+ || validationType === null
408
+ || (category === "caas") !== (fulfillment === "acme_subscription"))
409
+ return null;
410
+ const capabilities = record(source.capabilities);
411
+ const management = record(capabilities.management);
412
+ const commonName = record(capabilities.common_name);
413
+ const san = record(capabilities.san);
414
+ const offers = Array.isArray(source.offers)
415
+ ? source.offers.map(safeOffer).filter((offer) => offer !== null)
416
+ : [];
417
+ const includedSingle = nonNegativeInteger(san.included_single);
418
+ const includedWildcard = nonNegativeInteger(san.included_wildcard);
419
+ const minimum = nonNegativeInteger(san.min);
420
+ const maximum = nonNegativeInteger(san.max);
421
+ if (includedSingle === null
422
+ || includedWildcard === null
423
+ || minimum === null
424
+ || maximum === null
425
+ || maximum < minimum)
426
+ return null;
427
+ return {
428
+ id,
429
+ label,
430
+ category,
431
+ fulfillment,
432
+ validation_type: validationType,
433
+ brand: source.brand === null ? null : text(source.brand, 128),
434
+ capabilities: {
435
+ management: {
436
+ cancel: boolean(management.cancel),
437
+ reissue: boolean(management.reissue),
438
+ renew: boolean(management.renew),
439
+ revoke: boolean(management.revoke),
440
+ acme_credentials: boolean(management.acme_credentials),
441
+ domains: boolean(management.domains),
442
+ subscription_renewal: boolean(management.subscription_renewal),
443
+ },
444
+ common_name: {
445
+ single: boolean(commonName.single),
446
+ wildcard: boolean(commonName.wildcard),
447
+ ip: boolean(commonName.ip),
448
+ },
449
+ san: {
450
+ included_single: includedSingle,
451
+ included_wildcard: includedWildcard,
452
+ min: minimum,
453
+ max: maximum,
454
+ single: boolean(san.single),
455
+ wildcard: boolean(san.wildcard),
456
+ ip: boolean(san.ip),
457
+ },
458
+ },
459
+ offers,
460
+ };
461
+ }
462
+ function safeOrderDomain(value) {
463
+ const source = record(value);
464
+ const identifier = text(source.identifier, 253);
465
+ if (identifier === null)
466
+ return null;
467
+ return {
468
+ identifier,
469
+ name_kind: source.name_kind === "wildcard" ? "wildcard" : "single",
470
+ validation_method: text(source.validation_method, 253),
471
+ approved: boolean(source.approved),
472
+ validated_at: timestamp(source.validated_at),
473
+ };
474
+ }
475
+ function safeOrder(value) {
476
+ const source = record(value);
477
+ const id = certificateOrderIdSchema.safeParse(source.id);
478
+ const product = record(source.product);
479
+ const productId = integer(product.id);
480
+ const productLabel = text(product.label, 255);
481
+ const validationType = ["DV", "OV", "EV"].includes(String(product.validation_type))
482
+ ? String(product.validation_type)
483
+ : null;
484
+ const termMonths = integer(product.term_months);
485
+ const amount = record(source.amount);
486
+ const commonName = text(source.common_name, 253);
487
+ const net = money(amount.net);
488
+ const billingState = text(source.billing_state, 64);
489
+ const state = text(source.state, 64);
490
+ const artifactState = text(source.artifact_state, 64);
491
+ const createdAt = timestamp(source.created_at);
492
+ const updatedAt = timestamp(source.updated_at);
493
+ if (!id.success
494
+ || productId === null
495
+ || productLabel === null
496
+ || validationType === null
497
+ || termMonths === null
498
+ || commonName === null
499
+ || source.deployment_mode !== "customer_csr"
500
+ || !["order", "renew"].includes(String(source.operation))
501
+ || amount.currency !== "EUR"
502
+ || net === null
503
+ || billingState === null
504
+ || state === null
505
+ || artifactState === null
506
+ || createdAt === null
507
+ || updatedAt === null)
508
+ return null;
509
+ return {
510
+ id: id.data,
511
+ product: {
512
+ id: productId,
513
+ label: productLabel,
514
+ validation_type: validationType,
515
+ term_months: termMonths,
516
+ },
517
+ common_name: commonName,
518
+ domains: Array.isArray(source.domains)
519
+ ? source.domains.map(safeOrderDomain).filter((domain) => domain !== null)
520
+ : [],
521
+ deployment_mode: "customer_csr",
522
+ operation: source.operation,
523
+ renewal_of: source.renewal_of === null ? null : text(source.renewal_of, 36),
524
+ amount: {
525
+ currency: "EUR",
526
+ net,
527
+ },
528
+ billing_state: billingState,
529
+ payment_id: nullableInteger(source.payment_id),
530
+ refund_payment_id: nullableInteger(source.refund_payment_id),
531
+ refunded_at: timestamp(source.refunded_at),
532
+ state,
533
+ attention_required: boolean(source.attention_required),
534
+ subscription_begin_at: timestamp(source.subscription_begin_at),
535
+ subscription_end_at: timestamp(source.subscription_end_at),
536
+ artifact_state: artifactState,
537
+ download_available: boolean(source.download_available),
538
+ created_at: createdAt,
539
+ updated_at: updatedAt,
540
+ };
541
+ }
542
+ function safeQuote(value) {
543
+ const source = record(value);
544
+ const product = record(source.product);
545
+ const commonName = safeIdentifier(source.common_name);
546
+ const amount = record(source.amount);
547
+ const productId = integer(product.id);
548
+ const productLabel = text(product.label, 255);
549
+ const validationType = ["DV", "OV", "EV"].includes(String(product.validation_type))
550
+ ? String(product.validation_type)
551
+ : null;
552
+ const termMonths = integer(product.term_months);
553
+ const csrSha256 = typeof source.csr_sha256 === "string" && /^[a-f0-9]{64}$/.test(source.csr_sha256)
554
+ ? source.csr_sha256
555
+ : null;
556
+ const keyType = ["rsa", "ec-prime256v1", "ec-secp384r1", "ec-secp521r1"].includes(String(source.key_type))
557
+ ? String(source.key_type)
558
+ : null;
559
+ const base = money(amount.base);
560
+ const san = money(amount.san);
561
+ const net = money(amount.net);
562
+ const vat = money(amount.vat);
563
+ const vatRate = money(amount.vat_rate);
564
+ const total = money(amount.total);
565
+ if (commonName === null
566
+ || productId === null
567
+ || productLabel === null
568
+ || validationType === null
569
+ || termMonths === null
570
+ || csrSha256 === null
571
+ || keyType === null
572
+ || amount.currency !== "EUR"
573
+ || base === null
574
+ || san === null
575
+ || net === null
576
+ || vat === null
577
+ || vatRate === null
578
+ || total === null)
579
+ return null;
580
+ return {
581
+ operation: source.operation === "renew" ? "renew" : "order",
582
+ renewal: source.renewal === null ? null : {
583
+ certificate_order_id: text(record(source.renewal).certificate_order_id, 36),
584
+ remaining_days: Number.isInteger(record(source.renewal).remaining_days)
585
+ ? record(source.renewal).remaining_days
586
+ : null,
587
+ },
588
+ product: {
589
+ id: productId,
590
+ label: productLabel,
591
+ validation_type: validationType,
592
+ term_months: termMonths,
593
+ },
594
+ common_name: commonName,
595
+ alternative_names: Array.isArray(source.alternative_names)
596
+ ? source.alternative_names.map(safeIdentifier).filter((item) => item !== null)
597
+ : [],
598
+ csr_sha256: csrSha256,
599
+ key_type: keyType,
600
+ amount: {
601
+ currency: "EUR",
602
+ base,
603
+ san,
604
+ net,
605
+ vat,
606
+ vat_rate: vatRate,
607
+ total,
608
+ },
609
+ };
610
+ }
611
+ function safeValidation(value) {
612
+ const source = record(value);
613
+ const orderId = certificateOrderIdSchema.safeParse(source.order_id);
614
+ if (!orderId.success)
615
+ return null;
616
+ const domains = Array.isArray(source.domains) ? source.domains.map((item) => {
617
+ const domain = record(item);
618
+ const challenge = domain.challenge === null ? null : record(domain.challenge);
619
+ return {
620
+ identifier: text(domain.identifier, 253),
621
+ validation_method: text(domain.validation_method, 253),
622
+ approved: boolean(domain.approved),
623
+ challenge: challenge === null ? null : {
624
+ file_name: text(challenge.file_name, 1024),
625
+ value: text(challenge.value, 16384),
626
+ },
627
+ validated_at: timestamp(domain.validated_at),
628
+ };
629
+ }) : [];
630
+ return { order_id: orderId.data, state: text(source.state, 64), domains };
631
+ }
632
+ function safeArtifact(value) {
633
+ const source = record(value);
634
+ const orderId = certificateOrderIdSchema.safeParse(source.order_id);
635
+ if (!orderId.success || source.private_key_included !== false)
636
+ return null;
637
+ const pem = (candidate) => {
638
+ const value = text(candidate, 2_097_152);
639
+ return value !== null && value.includes("-----BEGIN CERTIFICATE-----") && !value.includes("PRIVATE KEY")
640
+ ? value
641
+ : null;
642
+ };
643
+ const generation = integer(source.generation);
644
+ const certificatePem = pem(source.certificate_pem);
645
+ const chainPem = pem(source.chain_pem);
646
+ const fullchainPem = pem(source.fullchain_pem);
647
+ const certificateSha256 = typeof source.certificate_sha256 === "string" && /^[a-f0-9]{64}$/.test(source.certificate_sha256)
648
+ ? source.certificate_sha256
649
+ : null;
650
+ if (generation === null
651
+ || certificatePem === null
652
+ || chainPem === null
653
+ || fullchainPem === null
654
+ || certificateSha256 === null)
655
+ return null;
656
+ return {
657
+ order_id: orderId.data,
658
+ generation,
659
+ certificate_pem: certificatePem,
660
+ chain_pem: chainPem,
661
+ fullchain_pem: fullchainPem,
662
+ certificate_sha256: certificateSha256,
663
+ identifiers: Array.isArray(source.identifiers)
664
+ ? source.identifiers.map((identifier) => text(identifier, 253)).filter((identifier) => identifier !== null)
665
+ : [],
666
+ not_before: timestamp(source.not_before),
667
+ not_after: timestamp(source.not_after),
668
+ fetched_at: timestamp(source.fetched_at),
669
+ private_key_included: false,
670
+ };
671
+ }
672
+ function safeAction(value) {
673
+ const source = record(value);
674
+ const id = certificateOrderIdSchema.safeParse(source.id);
675
+ const action = ["cancel", "recheck_validation", "resend_validation", "change_validation", "reissue"]
676
+ .includes(String(source.action)) ? source.action : null;
677
+ const state = ["queued", "submitting", "succeeded", "failed", "stale", "reconciliation_required"]
678
+ .includes(String(source.state)) ? source.state : null;
679
+ if (!id.success || action === null || state === null)
680
+ return null;
681
+ return {
682
+ id: id.data,
683
+ action,
684
+ state,
685
+ outcome_ambiguous: boolean(source.outcome_ambiguous),
686
+ attention_required: boolean(source.attention_required),
687
+ submitted_at: timestamp(source.submitted_at),
688
+ completed_at: timestamp(source.completed_at),
689
+ created_at: timestamp(source.created_at),
690
+ updated_at: timestamp(source.updated_at),
691
+ };
692
+ }
693
+ function safeAcmeSubscriptionDomain(value) {
694
+ const source = record(value);
695
+ const id = integer(source.id);
696
+ const name = certificateDnsIdentifierSchema.safeParse(source.name);
697
+ const nameKind = source.name_kind === "single" || source.name_kind === "wildcard"
698
+ ? source.name_kind
699
+ : null;
700
+ const state = ["requested", "active", "removing", "removed"].includes(String(source.state))
701
+ ? source.state
702
+ : null;
703
+ const replaceUntil = timestamp(source.replace_until);
704
+ if (id === null
705
+ || !name.success
706
+ || nameKind === null
707
+ || state === null
708
+ || typeof source.included !== "boolean"
709
+ || typeof source.can_remove !== "boolean"
710
+ || typeof source.can_replace !== "boolean"
711
+ || (source.replace_until !== null && replaceUntil === null))
712
+ return null;
713
+ if ((nameKind === "wildcard") !== name.data.startsWith("*."))
714
+ return null;
715
+ return {
716
+ id,
717
+ name: name.data,
718
+ name_kind: nameKind,
719
+ included: boolean(source.included),
720
+ state,
721
+ can_remove: source.can_remove,
722
+ can_replace: source.can_replace,
723
+ replace_until: replaceUntil,
724
+ };
725
+ }
726
+ function safeAcmeSubscriptionRenewal(value) {
727
+ const source = record(value);
728
+ const id = certificateSubscriptionIdSchema.safeParse(source.id);
729
+ const renewalAt = text(source.renewal_at, 64);
730
+ const state = [
731
+ "awaiting_payment",
732
+ "prepaid",
733
+ "settled",
734
+ "refund_pending",
735
+ "refunded",
736
+ "failed",
737
+ "manual_review",
738
+ ].includes(String(source.state)) ? source.state : null;
739
+ const billingState = [
740
+ "awaiting_payment",
741
+ "captured",
742
+ "settled",
743
+ "refund_pending",
744
+ "refunded",
745
+ "failed",
746
+ "billing_review_required",
747
+ ].includes(String(source.billing_state)) ? source.billing_state : null;
748
+ const domainCount = integer(source.domain_count);
749
+ const amount = record(source.amount);
750
+ const net = money(amount.net);
751
+ const createdAt = text(source.created_at, 64);
752
+ const updatedAt = text(source.updated_at, 64);
753
+ if (!id.success
754
+ || renewalAt === null
755
+ || state === null
756
+ || billingState === null
757
+ || domainCount === null
758
+ || domainCount > 255
759
+ || amount.currency !== "EUR"
760
+ || net === null
761
+ || createdAt === null
762
+ || updatedAt === null)
763
+ return null;
764
+ return {
765
+ id: id.data,
766
+ renewal_at: renewalAt,
767
+ state,
768
+ billing_state: billingState,
769
+ domain_count: domainCount,
770
+ amount: { currency: "EUR", net },
771
+ created_at: createdAt,
772
+ updated_at: updatedAt,
773
+ };
774
+ }
775
+ function safeAcmeSubscriptionAction(value) {
776
+ const source = record(value);
777
+ const id = certificateSubscriptionIdSchema.safeParse(source.id);
778
+ const action = ["cancel", "add_domain", "remove_domain", "replace_domain"]
779
+ .includes(String(source.action)) ? source.action : null;
780
+ const state = [
781
+ "awaiting_payment",
782
+ "queued",
783
+ "submitting",
784
+ "reconciling",
785
+ "reconciliation_required",
786
+ "succeeded",
787
+ "failed",
788
+ "manual_review",
789
+ ].includes(String(source.state)) ? source.state : null;
790
+ const billingState = [
791
+ "awaiting_payment",
792
+ "captured",
793
+ "paid",
794
+ "no_charge",
795
+ "billing_review_required",
796
+ "refund_required",
797
+ "refunded",
798
+ "failed",
799
+ ].includes(String(source.billing_state)) ? source.billing_state : null;
800
+ const amount = record(source.amount);
801
+ const net = money(amount.net);
802
+ const targetDomainId = nullableInteger(source.target_domain_id);
803
+ const createdAt = text(source.created_at, 64);
804
+ const updatedAt = text(source.updated_at, 64);
805
+ if (!id.success
806
+ || action === null
807
+ || state === null
808
+ || billingState === null
809
+ || typeof source.outcome_ambiguous !== "boolean"
810
+ || typeof source.attention_required !== "boolean"
811
+ || amount.currency !== "EUR"
812
+ || net === null
813
+ || (source.target_domain_id !== null && targetDomainId === null)
814
+ || createdAt === null
815
+ || updatedAt === null)
816
+ return null;
817
+ return {
818
+ id: id.data,
819
+ action,
820
+ state,
821
+ outcome_ambiguous: boolean(source.outcome_ambiguous),
822
+ attention_required: boolean(source.attention_required),
823
+ billing_state: billingState,
824
+ amount: { currency: "EUR", net },
825
+ target_domain_id: targetDomainId,
826
+ submitted_at: timestamp(source.submitted_at),
827
+ completed_at: timestamp(source.completed_at),
828
+ created_at: createdAt,
829
+ updated_at: updatedAt,
830
+ };
831
+ }
832
+ function safeAcmeSubscription(value) {
833
+ const source = record(value);
834
+ const id = certificateSubscriptionIdSchema.safeParse(source.id);
835
+ const product = record(source.product);
836
+ const productLabel = text(product.label, 255);
837
+ const termMonths = integer(product.term_months);
838
+ const state = [
839
+ "awaiting_payment",
840
+ "queued",
841
+ "provisioning",
842
+ "active",
843
+ "cancelled",
844
+ "failed",
845
+ "needs_attention",
846
+ ].includes(String(source.state)) ? source.state : null;
847
+ const billingState = [
848
+ "awaiting_payment",
849
+ "captured",
850
+ "paid",
851
+ "billing_review",
852
+ "refund_required",
853
+ "refund_pending",
854
+ "refunded",
855
+ "failed",
856
+ ].includes(String(source.billing_state)) ? source.billing_state : null;
857
+ const autoRenew = record(source.auto_renew);
858
+ const subscription = record(source.subscription);
859
+ const renewal = record(source.renewal);
860
+ const amount = record(source.amount);
861
+ const net = money(amount.net);
862
+ const createdAt = timestamp(source.created_at);
863
+ const updatedAt = timestamp(source.updated_at);
864
+ const providerEnabled = autoRenew.provider_enabled === null
865
+ ? null
866
+ : typeof autoRenew.provider_enabled === "boolean"
867
+ ? autoRenew.provider_enabled
868
+ : undefined;
869
+ const currentRenewal = renewal.current === null
870
+ ? null
871
+ : safeAcmeSubscriptionRenewal(renewal.current);
872
+ if (!id.success
873
+ || source.fulfillment !== "acme_subscription"
874
+ || productLabel === null
875
+ || termMonths === null
876
+ || state === null
877
+ || billingState === null
878
+ || typeof source.credentials_available !== "boolean"
879
+ || typeof autoRenew.enabled !== "boolean"
880
+ || providerEnabled === undefined
881
+ || amount.currency !== "EUR"
882
+ || net === null
883
+ || createdAt === null
884
+ || updatedAt === null
885
+ || typeof renewal.available !== "boolean"
886
+ || renewal.payment_source !== "balance"
887
+ || (renewal.current !== null && currentRenewal === null))
888
+ return null;
889
+ const rawDomains = Array.isArray(source.domains) ? source.domains : [];
890
+ const domains = rawDomains.map(safeAcmeSubscriptionDomain).filter((domain) => domain !== null);
891
+ if (domains.length === 0 || domains.length !== rawDomains.length)
892
+ return null;
893
+ return {
894
+ id: id.data,
895
+ fulfillment: "acme_subscription",
896
+ product: { label: productLabel, term_months: termMonths },
897
+ domains,
898
+ state,
899
+ billing_state: billingState,
900
+ credentials_available: boolean(source.credentials_available),
901
+ auto_renew: {
902
+ enabled: boolean(autoRenew.enabled),
903
+ provider_enabled: providerEnabled,
904
+ },
905
+ subscription: {
906
+ begins_at: timestamp(subscription.begins_at),
907
+ ends_at: timestamp(subscription.ends_at),
908
+ renews_at: timestamp(subscription.renews_at),
909
+ },
910
+ renewal: {
911
+ available: renewal.available,
912
+ payment_source: "balance",
913
+ current: currentRenewal,
914
+ },
915
+ amount: { currency: "EUR", net },
916
+ created_at: createdAt,
917
+ updated_at: updatedAt,
918
+ };
919
+ }
920
+ function safeAcmeSubscriptionQuote(value) {
921
+ const source = record(value);
922
+ const product = record(source.product);
923
+ const productId = integer(product.id);
924
+ const productLabel = text(product.label, 255);
925
+ const termMonths = integer(product.term_months);
926
+ const amount = record(source.amount);
927
+ const base = money(amount.base);
928
+ const domainsPrice = money(amount.domains);
929
+ const net = money(amount.net);
930
+ const vat = money(amount.vat);
931
+ const vatRate = money(amount.vat_rate);
932
+ const total = money(amount.total);
933
+ if (source.fulfillment !== "acme_subscription"
934
+ || productId === null
935
+ || productLabel === null
936
+ || termMonths === null
937
+ || typeof source.auto_renew !== "boolean"
938
+ || amount.currency !== "EUR"
939
+ || base === null
940
+ || domainsPrice === null
941
+ || net === null
942
+ || vat === null
943
+ || vatRate === null
944
+ || total === null)
945
+ return null;
946
+ const rawDomains = Array.isArray(source.domains) ? source.domains : [];
947
+ const domains = rawDomains.map((value) => {
948
+ const domain = record(value);
949
+ const name = certificateDnsIdentifierSchema.safeParse(domain.name);
950
+ const nameKind = domain.name_kind === "single" || domain.name_kind === "wildcard"
951
+ ? domain.name_kind
952
+ : null;
953
+ if (!name.success || nameKind === null || (nameKind === "wildcard") !== name.data.startsWith("*.")) {
954
+ return null;
955
+ }
956
+ return { name: name.data, name_kind: nameKind };
957
+ }).filter((domain) => domain !== null);
958
+ if (domains.length === 0 || domains.length !== rawDomains.length)
959
+ return null;
960
+ return {
961
+ fulfillment: "acme_subscription",
962
+ product: { id: productId, label: productLabel, term_months: termMonths },
963
+ domains,
964
+ auto_renew: boolean(source.auto_renew),
965
+ amount: {
966
+ currency: "EUR",
967
+ base,
968
+ domains: domainsPrice,
969
+ net,
970
+ vat,
971
+ vat_rate: vatRate,
972
+ total,
973
+ },
974
+ };
975
+ }
976
+ function safeAcmeSubscriptionDomainQuote(value) {
977
+ const source = record(value);
978
+ const subscriptionId = certificateSubscriptionIdSchema.safeParse(source.certificate_subscription_id);
979
+ const domain = record(source.domain);
980
+ const name = certificateDnsIdentifierSchema.safeParse(domain.name);
981
+ const nameKind = domain.name_kind === "single" || domain.name_kind === "wildcard"
982
+ ? domain.name_kind
983
+ : null;
984
+ const amount = record(source.amount);
985
+ const net = money(amount.net);
986
+ const vat = money(amount.vat);
987
+ const vatRate = money(amount.vat_rate);
988
+ const total = money(amount.total);
989
+ if (source.operation !== "add_domain"
990
+ || !subscriptionId.success
991
+ || !name.success
992
+ || nameKind === null
993
+ || (nameKind === "wildcard") !== name.data.startsWith("*.")
994
+ || amount.currency !== "EUR"
995
+ || net === null
996
+ || vat === null
997
+ || vatRate === null
998
+ || total === null)
999
+ return null;
1000
+ return {
1001
+ operation: "add_domain",
1002
+ certificate_subscription_id: subscriptionId.data,
1003
+ domain: { name: name.data, name_kind: nameKind },
1004
+ amount: { currency: "EUR", net, vat, vat_rate: vatRate, total },
1005
+ };
1006
+ }
1007
+ function safeAcmeSubscriptionRenewalQuote(value) {
1008
+ const source = record(value);
1009
+ const subscriptionId = certificateSubscriptionIdSchema.safeParse(source.certificate_subscription_id);
1010
+ const renewsAt = text(source.renews_at, 64);
1011
+ const domainCount = integer(source.domain_count);
1012
+ const amount = record(source.amount);
1013
+ const net = money(amount.net);
1014
+ const vat = money(amount.vat);
1015
+ const vatRate = money(amount.vat_rate);
1016
+ const total = money(amount.total);
1017
+ if (source.operation !== "renew_term"
1018
+ || !subscriptionId.success
1019
+ || renewsAt === null
1020
+ || domainCount === null
1021
+ || domainCount > 255
1022
+ || source.payment_source !== "balance"
1023
+ || amount.currency !== "EUR"
1024
+ || net === null
1025
+ || vat === null
1026
+ || vatRate === null
1027
+ || total === null)
1028
+ return null;
1029
+ return {
1030
+ operation: "renew_term",
1031
+ certificate_subscription_id: subscriptionId.data,
1032
+ renews_at: renewsAt,
1033
+ domain_count: domainCount,
1034
+ payment_source: "balance",
1035
+ amount: { currency: "EUR", net, vat, vat_rate: vatRate, total },
1036
+ };
1037
+ }
1038
+ const freeCertificateAuthorityNames = {
1039
+ letsencrypt: "Let's Encrypt",
1040
+ zerossl: "ZeroSSL",
1041
+ google: "Google Trust Services",
1042
+ };
1043
+ function safeFreeProviderOption(value) {
1044
+ const source = record(value);
1045
+ const id = freeCertificateAuthoritySchema.safeParse(source.id);
1046
+ if (!id.success
1047
+ || source.name !== freeCertificateAuthorityNames[id.data]
1048
+ || typeof source.default !== "boolean")
1049
+ return null;
1050
+ return { id: id.data, name: source.name, default: source.default };
1051
+ }
1052
+ function safeFreeKeyModeOption(value) {
1053
+ const source = record(value);
1054
+ if (!["managed", "customer_csr"].includes(String(source.mode))
1055
+ || typeof source.available !== "boolean"
1056
+ || typeof source.default !== "boolean"
1057
+ || (source.reason !== null && text(source.reason, 190) === null))
1058
+ return null;
1059
+ return {
1060
+ mode: source.mode,
1061
+ available: source.available,
1062
+ reason: source.reason === null ? null : text(source.reason, 190),
1063
+ default: source.default,
1064
+ };
1065
+ }
1066
+ function safeFreeMethodOption(value) {
1067
+ const source = record(value);
1068
+ if (![
1069
+ "dns_zone",
1070
+ "dns_cname",
1071
+ "http",
1072
+ "download",
1073
+ "auto_install_guest",
1074
+ "assistant_install",
1075
+ ].includes(String(source.method))
1076
+ || typeof source.available !== "boolean"
1077
+ || (source.reason !== null && text(source.reason, 190) === null)
1078
+ || (source.automatic !== undefined && typeof source.automatic !== "boolean"))
1079
+ return null;
1080
+ const option = {
1081
+ method: source.method,
1082
+ available: source.available,
1083
+ reason: source.reason === null ? null : text(source.reason, 190),
1084
+ };
1085
+ if (typeof source.automatic === "boolean")
1086
+ option.automatic = source.automatic;
1087
+ return option;
1088
+ }
1089
+ function safeFreeQuota(value) {
1090
+ const source = record(value);
1091
+ const pending = nonNegativeInteger(source.pending_requests);
1092
+ const maxPending = integer(source.max_pending_requests);
1093
+ const used = nonNegativeInteger(source.registered_domains_used_7d);
1094
+ const maximum = integer(source.max_registered_domains_7d);
1095
+ const domains = Array.isArray(source.registered_domains)
1096
+ ? source.registered_domains.map((domain) => certificateDnsIdentifierSchema.safeParse(domain))
1097
+ : [];
1098
+ if (pending === null
1099
+ || maxPending === null
1100
+ || used === null
1101
+ || maximum === null
1102
+ || !Array.isArray(source.registered_domains)
1103
+ || domains.some((domain) => !domain.success)
1104
+ || new Set(domains.map((domain) => domain.success ? domain.data : "")).size !== domains.length)
1105
+ return null;
1106
+ return {
1107
+ pending_requests: pending,
1108
+ max_pending_requests: maxPending,
1109
+ registered_domains_used_7d: used,
1110
+ max_registered_domains_7d: maximum,
1111
+ registered_domains: domains.map((domain) => domain.success ? domain.data : ""),
1112
+ };
1113
+ }
1114
+ function safeArray(value, mapper, maximum = 200) {
1115
+ if (!Array.isArray(value) || value.length > maximum)
1116
+ return null;
1117
+ const mapped = value.map(mapper);
1118
+ return mapped.some((item) => item === null) ? null : mapped;
1119
+ }
1120
+ function safeFreeEligibility(value) {
1121
+ const source = record(value);
1122
+ const providers = safeArray(source.certificate_authorities, safeFreeProviderOption, 3);
1123
+ const modes = safeArray(source.key_modes, safeFreeKeyModeOption, 2);
1124
+ const qualifiesVia = safeArray(source.qualifies_via, (item) => typeof item === "string" && /^[A-Za-z][A-Za-z0-9._-]{0,95}$/.test(item) ? item : null, 20);
1125
+ const quota = source.quota === undefined ? null : safeFreeQuota(source.quota);
1126
+ if (typeof source.eligible !== "boolean"
1127
+ || (source.reason !== null && text(source.reason, 190) === null)
1128
+ || providers === null
1129
+ || modes === null
1130
+ || qualifiesVia === null
1131
+ || (source.quota !== undefined && quota === null))
1132
+ return null;
1133
+ const result = {
1134
+ eligible: source.eligible,
1135
+ reason: source.reason === null ? null : text(source.reason, 190),
1136
+ qualifies_via: qualifiesVia,
1137
+ key_modes: modes,
1138
+ certificate_authorities: providers,
1139
+ };
1140
+ if (quota !== null)
1141
+ result.quota = quota;
1142
+ return result;
1143
+ }
1144
+ function safeFreePreflight(value) {
1145
+ const source = record(value);
1146
+ const hostname = certificateDnsIdentifierSchema.safeParse(source.hostname);
1147
+ const registeredDomain = certificateDnsIdentifierSchema.safeParse(source.registered_domain);
1148
+ const identifiers = safeArray(source.identifiers, (item) => {
1149
+ const parsed = certificateDnsIdentifierSchema.safeParse(item);
1150
+ return parsed.success ? parsed.data : null;
1151
+ }, 100);
1152
+ const validations = safeArray(source.validation_methods, safeFreeMethodOption, 3);
1153
+ const deliveries = safeArray(source.delivery_methods, safeFreeMethodOption, 3);
1154
+ const modes = safeArray(source.key_modes, safeFreeKeyModeOption, 2);
1155
+ const providers = safeArray(source.certificate_authorities, safeFreeProviderOption, 3);
1156
+ const recommended = record(source.recommended);
1157
+ const recommendedProvider = recommended.certificate_authority === null
1158
+ ? null
1159
+ : freeCertificateAuthoritySchema.safeParse(recommended.certificate_authority);
1160
+ if (!hostname.success
1161
+ || !registeredDomain.success
1162
+ || identifiers === null
1163
+ || identifiers.length === 0
1164
+ || new Set(identifiers).size !== identifiers.length
1165
+ || !identifiers.includes(hostname.success ? hostname.data : "")
1166
+ || validations === null
1167
+ || deliveries === null
1168
+ || modes === null
1169
+ || providers === null
1170
+ || validations.some((option) => !["dns_zone", "dns_cname", "http"].includes(String(option.method)))
1171
+ || deliveries.some((option) => !["download", "auto_install_guest", "assistant_install"].includes(String(option.method)))
1172
+ || typeof source.issuable !== "boolean"
1173
+ || (source.reason !== null && text(source.reason, 190) === null)
1174
+ || ![null, "dns_zone", "dns_cname", "http"].includes(recommended.validation_method)
1175
+ || ![null, "download", "auto_install_guest", "assistant_install"].includes(recommended.delivery_method)
1176
+ || !["managed", "customer_csr"].includes(String(recommended.key_mode))
1177
+ || (recommended.certificate_authority !== null && !recommendedProvider?.success))
1178
+ return null;
1179
+ return {
1180
+ hostname: hostname.data,
1181
+ identifiers,
1182
+ registered_domain: registeredDomain.data,
1183
+ issuable: source.issuable,
1184
+ reason: source.reason === null ? null : text(source.reason, 190),
1185
+ validation_methods: validations,
1186
+ delivery_methods: deliveries,
1187
+ key_modes: modes,
1188
+ certificate_authorities: providers,
1189
+ recommended: {
1190
+ validation_method: recommended.validation_method,
1191
+ delivery_method: recommended.delivery_method,
1192
+ key_mode: recommended.key_mode,
1193
+ certificate_authority: recommended.certificate_authority,
1194
+ },
1195
+ };
1196
+ }
1197
+ function safeFreeTimelineEvent(value) {
1198
+ const source = record(value);
1199
+ const event = text(source.event, 96);
1200
+ const createdAt = timestamp(source.created_at);
1201
+ if (event === null || !["customer", "system", "admin"].includes(String(source.actor)) || createdAt === null) {
1202
+ return null;
1203
+ }
1204
+ return { event, actor: source.actor, created_at: createdAt };
1205
+ }
1206
+ function safeFreeRequest(value) {
1207
+ const source = record(value);
1208
+ const id = freeCertificateRequestIdSchema.safeParse(source.id);
1209
+ const hostname = certificateDnsIdentifierSchema.safeParse(source.hostname);
1210
+ const registeredDomain = certificateDnsIdentifierSchema.safeParse(source.registered_domain);
1211
+ const state = freeCertificateStateSchema.safeParse(source.state);
1212
+ const identifiers = safeArray(source.identifiers, (item) => {
1213
+ const parsed = certificateDnsIdentifierSchema.safeParse(item);
1214
+ return parsed.success ? parsed.data : null;
1215
+ }, 100);
1216
+ const authorityId = source.certificate_authority_id === null
1217
+ ? null
1218
+ : freeCertificateAuthoritySchema.safeParse(source.certificate_authority_id);
1219
+ const authorityName = source.certificate_authority === null
1220
+ ? null
1221
+ : text(source.certificate_authority, 64);
1222
+ const deliveryOrderId = nullableInteger(source.delivery_order_id);
1223
+ const timeline = source.timeline === undefined
1224
+ ? undefined
1225
+ : safeArray(source.timeline, safeFreeTimelineEvent, 200);
1226
+ const createdAt = timestamp(source.created_at);
1227
+ if (!id.success
1228
+ || !hostname.success
1229
+ || !registeredDomain.success
1230
+ || !state.success
1231
+ || identifiers === null
1232
+ || identifiers.length === 0
1233
+ || new Set(identifiers).size !== identifiers.length
1234
+ || !identifiers.includes(hostname.success ? hostname.data : "")
1235
+ || !["managed", "customer_csr"].includes(String(source.key_mode))
1236
+ || !["dns_zone", "dns_cname"].includes(String(source.validation_method))
1237
+ || !["download", "auto_install_guest", "assistant_install"].includes(String(source.delivery_method))
1238
+ || (source.delivery_order_id !== null && deliveryOrderId === null)
1239
+ || (source.certificate_authority_id !== null && !authorityId?.success)
1240
+ || (source.certificate_authority !== null && authorityName === null)
1241
+ || (authorityId === null) !== (authorityName === null)
1242
+ || (authorityId !== null && authorityId.success && authorityName !== freeCertificateAuthorityNames[authorityId.data])
1243
+ || [
1244
+ "vpsnet_holds_private_key",
1245
+ "auto_renew",
1246
+ "renewal_requires_new_csr",
1247
+ "download_available",
1248
+ "revocable",
1249
+ "revocation_pending",
1250
+ "attention_required",
1251
+ ].some((field) => typeof source[field] !== "boolean")
1252
+ || ["issued_at", "not_before", "not_after", "renewal_due_at"]
1253
+ .some((field) => source[field] !== null && timestamp(source[field]) === null)
1254
+ || createdAt === null
1255
+ || timeline === null)
1256
+ return null;
1257
+ const result = {
1258
+ id: id.data,
1259
+ hostname: hostname.data,
1260
+ identifiers,
1261
+ registered_domain: registeredDomain.data,
1262
+ state: state.data,
1263
+ key_mode: source.key_mode,
1264
+ vpsnet_holds_private_key: source.vpsnet_holds_private_key,
1265
+ validation_method: source.validation_method,
1266
+ delivery_method: source.delivery_method,
1267
+ delivery_order_id: deliveryOrderId,
1268
+ auto_renew: source.auto_renew,
1269
+ renewal_requires_new_csr: source.renewal_requires_new_csr,
1270
+ issued_at: timestamp(source.issued_at),
1271
+ not_before: timestamp(source.not_before),
1272
+ not_after: timestamp(source.not_after),
1273
+ renewal_due_at: timestamp(source.renewal_due_at),
1274
+ certificate_authority_id: authorityId !== null && authorityId.success ? authorityId.data : null,
1275
+ certificate_authority: authorityName,
1276
+ download_available: source.download_available,
1277
+ revocable: source.revocable,
1278
+ revocation_pending: source.revocation_pending,
1279
+ attention_required: source.attention_required,
1280
+ created_at: createdAt,
1281
+ };
1282
+ if (timeline !== undefined)
1283
+ result.timeline = timeline;
1284
+ return result;
1285
+ }
1286
+ function safeFreeDnsRecord(value) {
1287
+ const source = record(value);
1288
+ const name = text(source.name, 253);
1289
+ const recordValue = text(source.value, 253);
1290
+ const ttl = integer(source.ttl);
1291
+ const dnsText = (candidate) => candidate !== null
1292
+ && candidate === candidate.toLowerCase()
1293
+ && !/[\s\x00-\x1f\x7f]/.test(candidate)
1294
+ && /^[a-z0-9_](?:[a-z0-9._-]{0,251}[a-z0-9.])?$/.test(candidate);
1295
+ if (source.type !== "CNAME"
1296
+ || !dnsText(name)
1297
+ || !dnsText(recordValue)
1298
+ || ttl === null
1299
+ || ttl < 60)
1300
+ return null;
1301
+ return { type: "CNAME", name, value: recordValue, ttl };
1302
+ }
1303
+ function safeFreeInstruction(value) {
1304
+ const source = record(value);
1305
+ const item = source.record === null ? null : safeFreeDnsRecord(source.record);
1306
+ const records = safeArray(source.records, safeFreeDnsRecord, 100);
1307
+ const noteKey = text(source.note_key, 190);
1308
+ const lastCheck = source.last_check === undefined ? undefined : record(source.last_check);
1309
+ if (!["dns_zone", "dns_cname", "http"].includes(String(source.validation_method))
1310
+ || typeof source.automatic !== "boolean"
1311
+ || (source.record !== null && item === null)
1312
+ || records === null
1313
+ || typeof source.verified !== "boolean"
1314
+ || noteKey === null
1315
+ || (lastCheck !== undefined
1316
+ && ((lastCheck.at !== null && timestamp(lastCheck.at) === null)
1317
+ || (lastCheck.detail !== null && text(lastCheck.detail, 500) === null))))
1318
+ return null;
1319
+ const result = {
1320
+ validation_method: source.validation_method,
1321
+ automatic: source.automatic,
1322
+ record: item,
1323
+ records,
1324
+ verified: source.verified,
1325
+ note_key: noteKey,
1326
+ };
1327
+ if (lastCheck !== undefined) {
1328
+ result.last_check = {
1329
+ at: timestamp(lastCheck.at),
1330
+ detail: lastCheck.detail === null ? null : text(lastCheck.detail, 500),
1331
+ };
1332
+ }
1333
+ return result;
1334
+ }
1335
+ function safeFreeArtifact(value) {
1336
+ const source = record(value);
1337
+ const pem = (candidate, allowEmpty = false) => {
1338
+ const value = text(candidate, 2_097_152);
1339
+ if (value === null || value.includes("PRIVATE KEY"))
1340
+ return null;
1341
+ if (allowEmpty && value === "")
1342
+ return value;
1343
+ return value.includes("-----BEGIN CERTIFICATE-----") ? value : null;
1344
+ };
1345
+ const certificate = pem(source.certificate);
1346
+ const chain = pem(source.chain, true);
1347
+ const fullchain = pem(source.fullchain);
1348
+ const notAfter = timestamp(source.not_after);
1349
+ const fingerprint = typeof source.fingerprint_sha256 === "string"
1350
+ && /^[a-f0-9]{64}$/.test(source.fingerprint_sha256)
1351
+ ? source.fingerprint_sha256
1352
+ : null;
1353
+ if (certificate === null || chain === null || fullchain === null || notAfter === null || fingerprint === null) {
1354
+ return null;
1355
+ }
1356
+ return { certificate, chain, fullchain, not_after: notAfter, fingerprint_sha256: fingerprint };
1357
+ }
1358
+ function safeError(status, value) {
1359
+ const source = record(value);
1360
+ const errors = Object.entries(source)
1361
+ .filter(([key, enabled]) => enabled === true && /^[A-Za-z][A-Za-z0-9._-]{0,95}$/.test(key))
1362
+ .map(([key]) => key)
1363
+ .slice(0, 20);
1364
+ return { success: false, status, errors };
1365
+ }
1366
+ /**
1367
+ * Defense-in-depth projection for the MCP boundary. Even if a future backend
1368
+ * response accidentally contains wholesale cost, provider IDs, credentials,
1369
+ * request bodies, or raw errors, none of those fields can enter model context.
1370
+ */
1371
+ export function safeCertificatePayload(kind, status, value) {
1372
+ const source = record(value);
1373
+ if (source.success !== true)
1374
+ return safeError(status, source);
1375
+ switch (kind) {
1376
+ case "catalog-list":
1377
+ return {
1378
+ success: true,
1379
+ records: Array.isArray(source.records)
1380
+ ? source.records.map(safeProduct).filter((product) => product !== null)
1381
+ : [],
1382
+ };
1383
+ case "catalog-product": {
1384
+ const product = safeProduct(source.product);
1385
+ return product === null ? safeError(502, { invalidCertificateResponse: true }) : { success: true, product };
1386
+ }
1387
+ case "order-list":
1388
+ return {
1389
+ success: true,
1390
+ records: Array.isArray(source.records)
1391
+ ? source.records.map(safeOrder).filter((order) => order !== null)
1392
+ : [],
1393
+ };
1394
+ case "order": {
1395
+ const order = safeOrder(source.order);
1396
+ return order === null ? safeError(502, { invalidCertificateResponse: true }) : { success: true, order };
1397
+ }
1398
+ case "quote": {
1399
+ const quote = safeQuote(source.quote);
1400
+ const quoteToken = text(source.quote_token, 190);
1401
+ return quote === null || quoteToken === null
1402
+ ? safeError(502, { invalidCertificateResponse: true })
1403
+ : {
1404
+ success: true,
1405
+ quote_token: quoteToken,
1406
+ quote_expires_at: timestamp(source.quote_expires_at),
1407
+ quote,
1408
+ };
1409
+ }
1410
+ case "confirmation": {
1411
+ const order = safeOrder(source.order);
1412
+ return order === null
1413
+ ? safeError(502, { invalidCertificateResponse: true })
1414
+ : {
1415
+ success: true,
1416
+ replayed: boolean(source.replayed),
1417
+ redirect: source.redirect === null ? null : text(source.redirect, 2048),
1418
+ payment_id: nullableInteger(source.payment_id),
1419
+ order,
1420
+ refund_policy: text(source.refund_policy, 1000),
1421
+ };
1422
+ }
1423
+ case "validation": {
1424
+ const validation = safeValidation(source.validation);
1425
+ return validation === null ? safeError(502, { invalidCertificateResponse: true }) : { success: true, validation };
1426
+ }
1427
+ case "artifact": {
1428
+ const artifact = safeArtifact(source.artifact);
1429
+ return artifact === null ? safeError(502, { invalidCertificateResponse: true }) : { success: true, artifact };
1430
+ }
1431
+ case "action-list":
1432
+ return {
1433
+ success: true,
1434
+ records: Array.isArray(source.records)
1435
+ ? source.records.map(safeAction).filter((action) => action !== null)
1436
+ : [],
1437
+ };
1438
+ case "action": {
1439
+ const action = safeAction(source.action);
1440
+ return action === null ? safeError(502, { invalidCertificateResponse: true }) : { success: true, action };
1441
+ }
1442
+ case "refresh":
1443
+ return source.reconciliation_queued === true
1444
+ ? { success: true, reconciliation_queued: true }
1445
+ : safeError(502, { invalidCertificateResponse: true });
1446
+ case "acme-subscription-list":
1447
+ return {
1448
+ success: true,
1449
+ records: Array.isArray(source.records)
1450
+ ? source.records.map(safeAcmeSubscription).filter((subscription) => subscription !== null)
1451
+ : [],
1452
+ };
1453
+ case "acme-subscription": {
1454
+ const subscription = safeAcmeSubscription(source.subscription);
1455
+ return subscription === null
1456
+ ? safeError(502, { invalidCertificateResponse: true })
1457
+ : { success: true, subscription };
1458
+ }
1459
+ case "acme-subscription-quote": {
1460
+ const quote = safeAcmeSubscriptionQuote(source.quote);
1461
+ const quoteToken = text(source.quote_token, 190);
1462
+ return quote === null || quoteToken === null
1463
+ ? safeError(502, { invalidCertificateResponse: true })
1464
+ : {
1465
+ success: true,
1466
+ quote_token: quoteToken,
1467
+ quote_expires_at: timestamp(source.quote_expires_at),
1468
+ quote,
1469
+ };
1470
+ }
1471
+ case "acme-subscription-confirmation": {
1472
+ const subscription = safeAcmeSubscription(source.subscription);
1473
+ return subscription === null
1474
+ ? safeError(502, { invalidCertificateResponse: true })
1475
+ : {
1476
+ success: true,
1477
+ replayed: boolean(source.replayed),
1478
+ redirect: source.redirect === null ? null : text(source.redirect, 2048),
1479
+ payment_id: nullableInteger(source.payment_id),
1480
+ subscription,
1481
+ refund_policy: text(source.refund_policy, 1000),
1482
+ };
1483
+ }
1484
+ case "acme-subscription-action-list":
1485
+ return {
1486
+ success: true,
1487
+ records: Array.isArray(source.records)
1488
+ ? source.records.map(safeAcmeSubscriptionAction).filter((action) => action !== null)
1489
+ : [],
1490
+ };
1491
+ case "acme-subscription-action": {
1492
+ const action = safeAcmeSubscriptionAction(source.action);
1493
+ return action === null
1494
+ ? safeError(502, { invalidCertificateResponse: true })
1495
+ : { success: true, action };
1496
+ }
1497
+ case "acme-subscription-refresh":
1498
+ return source.reconciliation_queued === true
1499
+ ? { success: true, reconciliation_queued: true }
1500
+ : safeError(502, { invalidCertificateResponse: true });
1501
+ case "acme-subscription-domain-quote": {
1502
+ const quote = safeAcmeSubscriptionDomainQuote(source.quote);
1503
+ const quoteToken = text(source.quote_token, 190);
1504
+ return quote === null || quoteToken === null
1505
+ ? safeError(502, { invalidCertificateResponse: true })
1506
+ : {
1507
+ success: true,
1508
+ quote_token: quoteToken,
1509
+ quote_expires_at: timestamp(source.quote_expires_at),
1510
+ quote,
1511
+ };
1512
+ }
1513
+ case "acme-subscription-domain-confirmation": {
1514
+ const action = safeAcmeSubscriptionAction(source.action);
1515
+ return action === null
1516
+ ? safeError(502, { invalidCertificateResponse: true })
1517
+ : {
1518
+ success: true,
1519
+ replayed: boolean(source.replayed),
1520
+ redirect: source.redirect === null ? null : text(source.redirect, 2048),
1521
+ payment_id: nullableInteger(source.payment_id),
1522
+ action,
1523
+ refund_policy: text(source.refund_policy, 1000),
1524
+ };
1525
+ }
1526
+ case "acme-subscription-renewal-quote": {
1527
+ const quote = safeAcmeSubscriptionRenewalQuote(source.quote);
1528
+ const quoteToken = text(source.quote_token, 190);
1529
+ return quote === null || quoteToken === null
1530
+ ? safeError(502, { invalidCertificateResponse: true })
1531
+ : {
1532
+ success: true,
1533
+ quote_token: quoteToken,
1534
+ quote_expires_at: timestamp(source.quote_expires_at),
1535
+ quote,
1536
+ };
1537
+ }
1538
+ case "acme-subscription-renewal-confirmation": {
1539
+ const renewal = safeAcmeSubscriptionRenewal(source.renewal);
1540
+ return renewal === null
1541
+ ? safeError(502, { invalidCertificateResponse: true })
1542
+ : {
1543
+ success: true,
1544
+ replayed: boolean(source.replayed),
1545
+ payment_id: nullableInteger(source.payment_id),
1546
+ payment_processing: boolean(source.payment_processing),
1547
+ renewal,
1548
+ refund_policy: text(source.refund_policy, 1000),
1549
+ };
1550
+ }
1551
+ case "free-eligibility": {
1552
+ const eligibility = safeFreeEligibility(source);
1553
+ return eligibility === null
1554
+ ? safeError(502, { invalidCertificateResponse: true })
1555
+ : { success: true, ...eligibility };
1556
+ }
1557
+ case "free-preflight": {
1558
+ const preflight = safeFreePreflight(source);
1559
+ return preflight === null
1560
+ ? safeError(502, { invalidCertificateResponse: true })
1561
+ : { success: true, ...preflight };
1562
+ }
1563
+ case "free-list": {
1564
+ const requests = safeArray(source.records, safeFreeRequest, 200);
1565
+ return requests === null
1566
+ ? safeError(502, { invalidCertificateResponse: true })
1567
+ : { success: true, records: requests };
1568
+ }
1569
+ case "free-request": {
1570
+ const request = safeFreeRequest(source.request);
1571
+ return request === null
1572
+ ? safeError(502, { invalidCertificateResponse: true })
1573
+ : { success: true, request };
1574
+ }
1575
+ case "free-create": {
1576
+ const request = safeFreeRequest(source.request);
1577
+ const instruction = safeFreeInstruction(source.instruction);
1578
+ const csrSha256 = source.csr_sha256 === null
1579
+ ? null
1580
+ : typeof source.csr_sha256 === "string" && /^[a-f0-9]{64}$/.test(source.csr_sha256)
1581
+ ? source.csr_sha256
1582
+ : undefined;
1583
+ return request === null
1584
+ || instruction === null
1585
+ || csrSha256 === undefined
1586
+ || typeof source.replayed !== "boolean"
1587
+ ? safeError(502, { invalidCertificateResponse: true })
1588
+ : {
1589
+ success: true,
1590
+ request,
1591
+ instruction,
1592
+ csr_sha256: csrSha256,
1593
+ replayed: source.replayed,
1594
+ };
1595
+ }
1596
+ case "free-instruction": {
1597
+ const instruction = safeFreeInstruction(source);
1598
+ return instruction === null
1599
+ ? safeError(502, { invalidCertificateResponse: true })
1600
+ : { success: true, ...instruction };
1601
+ }
1602
+ case "free-artifact": {
1603
+ const artifact = safeFreeArtifact(source.artifact);
1604
+ return artifact === null
1605
+ || !["managed", "customer_csr"].includes(String(source.key_mode))
1606
+ || source.private_key_included !== false
1607
+ ? safeError(502, { invalidCertificateResponse: true })
1608
+ : {
1609
+ success: true,
1610
+ key_mode: source.key_mode,
1611
+ artifact,
1612
+ private_key_included: false,
1613
+ };
1614
+ }
1615
+ case "free-action":
1616
+ return ["renew", "revoke", "recheck", "cancel"].includes(String(source.action))
1617
+ && source.queued === true
1618
+ ? { success: true, action: source.action, queued: true }
1619
+ : safeError(502, { invalidCertificateResponse: true });
1620
+ }
1621
+ }