vpsnet-mcp 1.0.9 → 2.1.0

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