@varde-flyt/vfac 0.7.1 → 0.8.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.
- package/dist/vfac.mjs +1196 -367
- package/package.json +1 -1
package/dist/vfac.mjs
CHANGED
|
@@ -11988,6 +11988,14 @@ var coerce = {
|
|
|
11988
11988
|
};
|
|
11989
11989
|
var NEVER = INVALID;
|
|
11990
11990
|
|
|
11991
|
+
// ../product-configuration/dist/configuration-bounds.js
|
|
11992
|
+
var MAX_CONFIGURATION_DEPTH = 2;
|
|
11993
|
+
var MAX_CONFIGURATION_LEAVES = 40;
|
|
11994
|
+
var MAX_CONFIGURATION_NODES = 60;
|
|
11995
|
+
var MAX_CONFIGURATION_VALUE_LEAVES = 1e3;
|
|
11996
|
+
var MAX_CONFIGURATION_ISSUES = 50;
|
|
11997
|
+
var MAX_CONFIGURATION_VALUE_BYTES = 16384;
|
|
11998
|
+
|
|
11991
11999
|
// ../product-configuration/dist/json-schema-annex.js
|
|
11992
12000
|
var ANNEXES = /* @__PURE__ */ new WeakMap();
|
|
11993
12001
|
function withJsonSchemaAnnex(schema, annex) {
|
|
@@ -12287,12 +12295,49 @@ var ArrayPropertySchema = external_exports.object({
|
|
|
12287
12295
|
uniqueItems: external_exports.boolean().optional(),
|
|
12288
12296
|
default: external_exports.array(external_exports.string().max(200)).max(100).optional()
|
|
12289
12297
|
}).strict();
|
|
12298
|
+
var MAX_CONFIGURATION_PROPERTIES = 40;
|
|
12290
12299
|
var ConfigurationPropertySchema = external_exports.discriminatedUnion("type", [
|
|
12291
12300
|
StringPropertySchema,
|
|
12292
12301
|
NumberPropertySchema,
|
|
12293
12302
|
BooleanPropertySchema,
|
|
12294
12303
|
ArrayPropertySchema
|
|
12295
12304
|
]);
|
|
12305
|
+
var NestedStringPropertySchema = StringPropertySchema.omit({
|
|
12306
|
+
"x-secret": true,
|
|
12307
|
+
writeOnly: true
|
|
12308
|
+
});
|
|
12309
|
+
var NestedConfigurationPropertySchema = external_exports.discriminatedUnion("type", [
|
|
12310
|
+
NestedStringPropertySchema,
|
|
12311
|
+
NumberPropertySchema,
|
|
12312
|
+
BooleanPropertySchema,
|
|
12313
|
+
ArrayPropertySchema
|
|
12314
|
+
]);
|
|
12315
|
+
var nestedPropertiesShape = {
|
|
12316
|
+
properties: external_exports.record(PropertyNameSchema, NestedConfigurationPropertySchema),
|
|
12317
|
+
required: external_exports.array(PropertyNameSchema).max(MAX_CONFIGURATION_PROPERTIES).optional(),
|
|
12318
|
+
additionalProperties: external_exports.literal(false)
|
|
12319
|
+
};
|
|
12320
|
+
var ObjectPropertySchema = external_exports.object({
|
|
12321
|
+
type: external_exports.literal("object"),
|
|
12322
|
+
title: TitleSchema,
|
|
12323
|
+
description: HelpTextSchema.optional(),
|
|
12324
|
+
group: ConfigurationGroupSchema,
|
|
12325
|
+
...nestedPropertiesShape
|
|
12326
|
+
}).strict();
|
|
12327
|
+
var ObjectArrayItemsSchema = external_exports.object({
|
|
12328
|
+
type: external_exports.literal("object"),
|
|
12329
|
+
...nestedPropertiesShape
|
|
12330
|
+
}).strict();
|
|
12331
|
+
var ArrayPropertyV2Schema = ArrayPropertySchema.extend({
|
|
12332
|
+
items: external_exports.discriminatedUnion("type", [ArrayItemsSchema, ObjectArrayItemsSchema])
|
|
12333
|
+
});
|
|
12334
|
+
var RootConfigurationPropertySchema = external_exports.discriminatedUnion("type", [
|
|
12335
|
+
StringPropertySchema,
|
|
12336
|
+
NumberPropertySchema,
|
|
12337
|
+
BooleanPropertySchema,
|
|
12338
|
+
ArrayPropertyV2Schema,
|
|
12339
|
+
ObjectPropertySchema
|
|
12340
|
+
]);
|
|
12296
12341
|
var CustomerConfigurationObjectSchema = external_exports.object({
|
|
12297
12342
|
type: external_exports.literal("object"),
|
|
12298
12343
|
properties: external_exports.record(PropertyNameSchema, ConfigurationPropertySchema).describe("Customer-editable settings, keyed by camelCase property name."),
|
|
@@ -12326,7 +12371,6 @@ var CustomerConfigurationObjectSchema = external_exports.object({
|
|
|
12326
12371
|
*/
|
|
12327
12372
|
additionalProperties: external_exports.literal(false)
|
|
12328
12373
|
}).strict();
|
|
12329
|
-
var MAX_CONFIGURATION_PROPERTIES = 40;
|
|
12330
12374
|
var CustomerConfigurationSchema = CustomerConfigurationObjectSchema.superRefine((config, ctx) => {
|
|
12331
12375
|
const names = Object.keys(config.properties);
|
|
12332
12376
|
if (names.length > MAX_CONFIGURATION_PROPERTIES) {
|
|
@@ -12338,182 +12382,192 @@ var CustomerConfigurationSchema = CustomerConfigurationObjectSchema.superRefine(
|
|
|
12338
12382
|
}
|
|
12339
12383
|
for (const name of names) {
|
|
12340
12384
|
const property = config.properties[name];
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12385
|
+
checkDeclaredProperty(name, property, ["properties", name], ctx, true);
|
|
12386
|
+
}
|
|
12387
|
+
for (const name of config.required ?? []) {
|
|
12388
|
+
if (!Object.hasOwn(config.properties, name)) {
|
|
12344
12389
|
ctx.addIssue({
|
|
12345
12390
|
code: external_exports.ZodIssueCode.custom,
|
|
12346
|
-
path,
|
|
12347
|
-
message:
|
|
12391
|
+
path: ["required"],
|
|
12392
|
+
message: `"${name}" is listed as required but is not a declared property.`
|
|
12348
12393
|
});
|
|
12349
12394
|
}
|
|
12395
|
+
}
|
|
12396
|
+
const duplicates = (config.required ?? []).filter((name, index, all) => all.indexOf(name) !== index);
|
|
12397
|
+
if (duplicates.length > 0) {
|
|
12398
|
+
ctx.addIssue({
|
|
12399
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12400
|
+
path: ["required"],
|
|
12401
|
+
message: `Duplicate required entries: ${[...new Set(duplicates)].join(", ")}.`
|
|
12402
|
+
});
|
|
12403
|
+
}
|
|
12404
|
+
checkDependentRequired(config, ctx);
|
|
12405
|
+
});
|
|
12406
|
+
function checkDeclaredProperty(name, property, path, ctx, atRoot) {
|
|
12407
|
+
const infrastructure = infrastructureVocabularyViolation(name);
|
|
12408
|
+
if (infrastructure) {
|
|
12409
|
+
ctx.addIssue({
|
|
12410
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12411
|
+
path,
|
|
12412
|
+
message: `${infrastructure}. Customer settings describe outcomes, not infrastructure.`
|
|
12413
|
+
});
|
|
12414
|
+
}
|
|
12415
|
+
if (atRoot) {
|
|
12350
12416
|
const platformOwned = platformOwnedFieldViolation(name);
|
|
12351
12417
|
if (platformOwned) {
|
|
12352
12418
|
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message: `${platformOwned}.` });
|
|
12353
12419
|
}
|
|
12354
|
-
|
|
12355
|
-
|
|
12356
|
-
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12360
|
-
path: [...path, label],
|
|
12361
|
-
message: `${violation}. Customer settings offer outcomes, not infrastructure sizes.`
|
|
12362
|
-
});
|
|
12363
|
-
}
|
|
12364
|
-
}
|
|
12365
|
-
}
|
|
12366
|
-
if (property.type === "string") {
|
|
12367
|
-
const secret = property["x-secret"] === true;
|
|
12368
|
-
const credential = credentialNameViolation(name);
|
|
12369
|
-
if (credential && !secret) {
|
|
12370
|
-
ctx.addIssue({
|
|
12371
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12372
|
-
path,
|
|
12373
|
-
message: `${credential} and must be declared "x-secret": true with "writeOnly": true, or renamed if it is not one.`
|
|
12374
|
-
});
|
|
12375
|
-
}
|
|
12376
|
-
if (secret && property.writeOnly !== true) {
|
|
12377
|
-
ctx.addIssue({
|
|
12378
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12379
|
-
path,
|
|
12380
|
-
message: `"${name}" is marked x-secret but not writeOnly \u2014 a read API could echo the value.`
|
|
12381
|
-
});
|
|
12382
|
-
}
|
|
12383
|
-
if (property.writeOnly === true && !secret) {
|
|
12384
|
-
ctx.addIssue({
|
|
12385
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12386
|
-
path,
|
|
12387
|
-
message: `"${name}" is marked writeOnly but not x-secret \u2014 the value would not be routed to the secret flow.`
|
|
12388
|
-
});
|
|
12389
|
-
}
|
|
12390
|
-
if (secret && property.default !== void 0) {
|
|
12391
|
-
ctx.addIssue({
|
|
12392
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12393
|
-
path: [...path, "default"],
|
|
12394
|
-
message: `"${name}" is a secret and must not declare a default value.`
|
|
12395
|
-
});
|
|
12396
|
-
}
|
|
12397
|
-
if (secret && property.enum !== void 0) {
|
|
12398
|
-
ctx.addIssue({
|
|
12399
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12400
|
-
path: [...path, "enum"],
|
|
12401
|
-
message: `"${name}" is a secret; an enum would enumerate candidate secret values.`
|
|
12402
|
-
});
|
|
12403
|
-
}
|
|
12404
|
-
if (property.enum === void 0 && property.maxLength === void 0) {
|
|
12405
|
-
ctx.addIssue({
|
|
12406
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12407
|
-
path,
|
|
12408
|
-
message: `"${name}" must declare either an enum or a maxLength.`
|
|
12409
|
-
});
|
|
12410
|
-
}
|
|
12411
|
-
if (property.enum !== void 0 && property.default !== void 0 && !property.enum.includes(property.default)) {
|
|
12412
|
-
ctx.addIssue({
|
|
12413
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12414
|
-
path: [...path, "default"],
|
|
12415
|
-
message: `"${name}" declares a default outside its enum.`
|
|
12416
|
-
});
|
|
12417
|
-
}
|
|
12418
|
-
if (property.minLength !== void 0 && property.maxLength !== void 0 && property.minLength > property.maxLength) {
|
|
12419
|
-
ctx.addIssue({
|
|
12420
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12421
|
-
path,
|
|
12422
|
-
message: `"${name}" has minLength greater than maxLength.`
|
|
12423
|
-
});
|
|
12424
|
-
}
|
|
12425
|
-
if (property.default !== void 0 && property.maxLength !== void 0 && property.default.length > property.maxLength) {
|
|
12426
|
-
ctx.addIssue({
|
|
12427
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12428
|
-
path: [...path, "default"],
|
|
12429
|
-
message: `"${name}" declares a default longer than its own maxLength.`
|
|
12430
|
-
});
|
|
12431
|
-
}
|
|
12432
|
-
if (property.pattern !== void 0 && !isSafeRegex(property.pattern)) {
|
|
12420
|
+
}
|
|
12421
|
+
for (const [label, values] of enumerableValues(property)) {
|
|
12422
|
+
for (const value of values) {
|
|
12423
|
+
const violation = infrastructureValueViolation(value);
|
|
12424
|
+
if (violation) {
|
|
12433
12425
|
ctx.addIssue({
|
|
12434
12426
|
code: external_exports.ZodIssueCode.custom,
|
|
12435
|
-
path: [...path,
|
|
12436
|
-
message:
|
|
12427
|
+
path: [...path, label],
|
|
12428
|
+
message: `${violation}. Customer settings offer outcomes, not infrastructure sizes.`
|
|
12437
12429
|
});
|
|
12438
12430
|
}
|
|
12439
12431
|
}
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12432
|
+
}
|
|
12433
|
+
if (property.type === "string") {
|
|
12434
|
+
const secret = property["x-secret"] === true;
|
|
12435
|
+
const credential = credentialNameViolation(name);
|
|
12436
|
+
if (credential && !secret) {
|
|
12437
|
+
ctx.addIssue({
|
|
12438
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12439
|
+
path,
|
|
12440
|
+
// THE REMEDIATION HAS TO BE ONE THE CONTRACT ALLOWS. At the root, the
|
|
12441
|
+
// answer is to declare the two markers. Below it, that answer is
|
|
12442
|
+
// IMPOSSIBLE — the nested shape omits both keys and `.strict()` refuses
|
|
12443
|
+
// them — so telling a publisher to add them sends them to write a
|
|
12444
|
+
// second invalid document, and an agent following the validator loops.
|
|
12445
|
+
// A validator's errors are part of the agent-facing contract.
|
|
12446
|
+
message: atRoot ? `${credential} and must be declared "x-secret": true with "writeOnly": true, or renamed if it is not one.` : `${credential}, and a credential must be a TOP-LEVEL setting in this contract format \u2014 move it out of the group and declare it "x-secret": true with "writeOnly": true, or rename it if it is not one.`
|
|
12447
|
+
});
|
|
12448
|
+
}
|
|
12449
|
+
if (secret && property.writeOnly !== true) {
|
|
12450
|
+
ctx.addIssue({
|
|
12451
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12452
|
+
path,
|
|
12453
|
+
message: `"${name}" is marked x-secret but not writeOnly \u2014 a read API could echo the value.`
|
|
12454
|
+
});
|
|
12455
|
+
}
|
|
12456
|
+
if (property.writeOnly === true && !secret) {
|
|
12457
|
+
ctx.addIssue({
|
|
12458
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12459
|
+
path,
|
|
12460
|
+
message: `"${name}" is marked writeOnly but not x-secret \u2014 the value would not be routed to the secret flow.`
|
|
12461
|
+
});
|
|
12462
|
+
}
|
|
12463
|
+
if (secret && property.default !== void 0) {
|
|
12464
|
+
ctx.addIssue({
|
|
12465
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12466
|
+
path: [...path, "default"],
|
|
12467
|
+
message: `"${name}" is a secret and must not declare a default value.`
|
|
12468
|
+
});
|
|
12469
|
+
}
|
|
12470
|
+
if (secret && property.enum !== void 0) {
|
|
12471
|
+
ctx.addIssue({
|
|
12472
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12473
|
+
path: [...path, "enum"],
|
|
12474
|
+
message: `"${name}" is a secret; an enum would enumerate candidate secret values.`
|
|
12475
|
+
});
|
|
12476
|
+
}
|
|
12477
|
+
if (property.enum === void 0 && property.maxLength === void 0) {
|
|
12478
|
+
ctx.addIssue({
|
|
12479
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12480
|
+
path,
|
|
12481
|
+
message: `"${name}" must declare either an enum or a maxLength.`
|
|
12482
|
+
});
|
|
12483
|
+
}
|
|
12484
|
+
if (property.enum !== void 0 && property.default !== void 0 && !property.enum.includes(property.default)) {
|
|
12485
|
+
ctx.addIssue({
|
|
12486
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12487
|
+
path: [...path, "default"],
|
|
12488
|
+
message: `"${name}" declares a default outside its enum.`
|
|
12489
|
+
});
|
|
12490
|
+
}
|
|
12491
|
+
if (property.minLength !== void 0 && property.maxLength !== void 0 && property.minLength > property.maxLength) {
|
|
12492
|
+
ctx.addIssue({
|
|
12493
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12494
|
+
path,
|
|
12495
|
+
message: `"${name}" has minLength greater than maxLength.`
|
|
12496
|
+
});
|
|
12497
|
+
}
|
|
12498
|
+
if (property.default !== void 0 && property.maxLength !== void 0 && property.default.length > property.maxLength) {
|
|
12499
|
+
ctx.addIssue({
|
|
12500
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12501
|
+
path: [...path, "default"],
|
|
12502
|
+
message: `"${name}" declares a default longer than its own maxLength.`
|
|
12503
|
+
});
|
|
12504
|
+
}
|
|
12505
|
+
if (property.pattern !== void 0 && !isSafeRegex(property.pattern)) {
|
|
12506
|
+
ctx.addIssue({
|
|
12507
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12508
|
+
path: [...path, "pattern"],
|
|
12509
|
+
message: `"${name}" declares a pattern that is not a valid regular expression.`
|
|
12510
|
+
});
|
|
12511
|
+
}
|
|
12512
|
+
}
|
|
12513
|
+
if (property.type === "integer" || property.type === "number") {
|
|
12514
|
+
if (property.minimum > property.maximum) {
|
|
12515
|
+
ctx.addIssue({
|
|
12516
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12517
|
+
path,
|
|
12518
|
+
message: `"${name}" has minimum greater than maximum.`
|
|
12519
|
+
});
|
|
12520
|
+
}
|
|
12521
|
+
if (property.default !== void 0 && (property.default < property.minimum || property.default > property.maximum)) {
|
|
12522
|
+
ctx.addIssue({
|
|
12523
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12524
|
+
path: [...path, "default"],
|
|
12525
|
+
message: `"${name}" declares a default outside its minimum/maximum range.`
|
|
12526
|
+
});
|
|
12527
|
+
}
|
|
12528
|
+
if (property.type === "integer" && !Number.isInteger(property.default ?? 0)) {
|
|
12529
|
+
ctx.addIssue({
|
|
12530
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12531
|
+
path: [...path, "default"],
|
|
12532
|
+
message: `"${name}" is an integer but declares a fractional default.`
|
|
12533
|
+
});
|
|
12534
|
+
}
|
|
12535
|
+
}
|
|
12536
|
+
if (property.type === "array") {
|
|
12537
|
+
const allowed = property.items.enum;
|
|
12538
|
+
if (allowed === void 0 && property.items.maxLength === void 0) {
|
|
12539
|
+
ctx.addIssue({
|
|
12540
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12541
|
+
path: [...path, "items"],
|
|
12542
|
+
message: `"${name}" items must declare either an enum or a maxLength.`
|
|
12543
|
+
});
|
|
12544
|
+
}
|
|
12545
|
+
if (property.minItems !== void 0 && property.minItems > property.maxItems) {
|
|
12546
|
+
ctx.addIssue({
|
|
12547
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12548
|
+
path,
|
|
12549
|
+
message: `"${name}" has minItems greater than maxItems.`
|
|
12550
|
+
});
|
|
12551
|
+
}
|
|
12552
|
+
if (property.default !== void 0) {
|
|
12553
|
+
if (property.default.length > property.maxItems) {
|
|
12449
12554
|
ctx.addIssue({
|
|
12450
12555
|
code: external_exports.ZodIssueCode.custom,
|
|
12451
12556
|
path: [...path, "default"],
|
|
12452
|
-
message: `"${name}" declares a default
|
|
12557
|
+
message: `"${name}" declares a default longer than maxItems.`
|
|
12453
12558
|
});
|
|
12454
12559
|
}
|
|
12455
|
-
|
|
12560
|
+
const outside = allowed ? property.default.filter((value) => !allowed.includes(value)) : [];
|
|
12561
|
+
if (outside.length > 0) {
|
|
12456
12562
|
ctx.addIssue({
|
|
12457
12563
|
code: external_exports.ZodIssueCode.custom,
|
|
12458
12564
|
path: [...path, "default"],
|
|
12459
|
-
message: `"${name}"
|
|
12460
|
-
});
|
|
12461
|
-
}
|
|
12462
|
-
}
|
|
12463
|
-
if (property.type === "array") {
|
|
12464
|
-
const allowed = property.items.enum;
|
|
12465
|
-
if (allowed === void 0 && property.items.maxLength === void 0) {
|
|
12466
|
-
ctx.addIssue({
|
|
12467
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12468
|
-
path: [...path, "items"],
|
|
12469
|
-
message: `"${name}" items must declare either an enum or a maxLength.`
|
|
12470
|
-
});
|
|
12471
|
-
}
|
|
12472
|
-
if (property.minItems !== void 0 && property.minItems > property.maxItems) {
|
|
12473
|
-
ctx.addIssue({
|
|
12474
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12475
|
-
path,
|
|
12476
|
-
message: `"${name}" has minItems greater than maxItems.`
|
|
12565
|
+
message: `"${name}" declares default values outside its items enum: ${outside.join(", ")}.`
|
|
12477
12566
|
});
|
|
12478
12567
|
}
|
|
12479
|
-
if (property.default !== void 0) {
|
|
12480
|
-
if (property.default.length > property.maxItems) {
|
|
12481
|
-
ctx.addIssue({
|
|
12482
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12483
|
-
path: [...path, "default"],
|
|
12484
|
-
message: `"${name}" declares a default longer than maxItems.`
|
|
12485
|
-
});
|
|
12486
|
-
}
|
|
12487
|
-
const outside = allowed ? property.default.filter((value) => !allowed.includes(value)) : [];
|
|
12488
|
-
if (outside.length > 0) {
|
|
12489
|
-
ctx.addIssue({
|
|
12490
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12491
|
-
path: [...path, "default"],
|
|
12492
|
-
message: `"${name}" declares default values outside its items enum: ${outside.join(", ")}.`
|
|
12493
|
-
});
|
|
12494
|
-
}
|
|
12495
|
-
}
|
|
12496
12568
|
}
|
|
12497
12569
|
}
|
|
12498
|
-
|
|
12499
|
-
if (!Object.hasOwn(config.properties, name)) {
|
|
12500
|
-
ctx.addIssue({
|
|
12501
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12502
|
-
path: ["required"],
|
|
12503
|
-
message: `"${name}" is listed as required but is not a declared property.`
|
|
12504
|
-
});
|
|
12505
|
-
}
|
|
12506
|
-
}
|
|
12507
|
-
const duplicates = (config.required ?? []).filter((name, index, all) => all.indexOf(name) !== index);
|
|
12508
|
-
if (duplicates.length > 0) {
|
|
12509
|
-
ctx.addIssue({
|
|
12510
|
-
code: external_exports.ZodIssueCode.custom,
|
|
12511
|
-
path: ["required"],
|
|
12512
|
-
message: `Duplicate required entries: ${[...new Set(duplicates)].join(", ")}.`
|
|
12513
|
-
});
|
|
12514
|
-
}
|
|
12515
|
-
checkDependentRequired(config, ctx);
|
|
12516
|
-
});
|
|
12570
|
+
}
|
|
12517
12571
|
function checkDependentRequired(config, ctx) {
|
|
12518
12572
|
const clauses = Object.entries(config.dependentRequired ?? {});
|
|
12519
12573
|
if (clauses.length === 0)
|
|
@@ -12623,41 +12677,412 @@ function checkOneSecretPerGroup(config, ctx) {
|
|
|
12623
12677
|
queue.push(next);
|
|
12624
12678
|
}
|
|
12625
12679
|
}
|
|
12626
|
-
const secrets = component.filter(isSecret2).sort();
|
|
12627
|
-
if (secrets.length <= 1)
|
|
12680
|
+
const secrets = component.filter(isSecret2).sort();
|
|
12681
|
+
if (secrets.length <= 1)
|
|
12682
|
+
continue;
|
|
12683
|
+
ctx.addIssue({
|
|
12684
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12685
|
+
// The component has no single name, so the issue is reported against the
|
|
12686
|
+
// map rather than against whichever member happened to be visited first.
|
|
12687
|
+
path: ["dependentRequired"],
|
|
12688
|
+
message: `These settings are configured together and include more than one secret (${secrets.join(", ")}). Only one secret can be supplied per change, so a group must ask for at most one \u2014 otherwise completing it on a running resource takes several, in an order the customer has to work out.`
|
|
12689
|
+
});
|
|
12690
|
+
}
|
|
12691
|
+
}
|
|
12692
|
+
var CustomerConfigurationV2ObjectSchema = external_exports.object({
|
|
12693
|
+
type: external_exports.literal("object"),
|
|
12694
|
+
properties: external_exports.record(PropertyNameSchema, RootConfigurationPropertySchema).describe("Customer-editable settings, keyed by camelCase property name."),
|
|
12695
|
+
required: external_exports.array(PropertyNameSchema).max(MAX_CONFIGURATION_PROPERTIES).optional(),
|
|
12696
|
+
/**
|
|
12697
|
+
* ROOT PROPERTIES ONLY, in v2.0.
|
|
12698
|
+
*
|
|
12699
|
+
* The published key promises that "a publisher running an off-the-shelf
|
|
12700
|
+
* validator over that file must get the answer the platform gives", and
|
|
12701
|
+
* JSON Schema 2020-12 `dependentRequired` is scoped to the object that
|
|
12702
|
+
* carries it. A clause naming a nested leaf would be a rule no standard
|
|
12703
|
+
* validator applies, which is the one thing this key may not become. A
|
|
12704
|
+
* nested object may not carry its own clause either — that is expressible
|
|
12705
|
+
* and honest, and it is deliberately left for when something needs it.
|
|
12706
|
+
*/
|
|
12707
|
+
dependentRequired: external_exports.record(PropertyNameSchema, external_exports.array(PropertyNameSchema).min(1).max(MAX_CONFIGURATION_PROPERTIES)).optional().describe("Settings that must be supplied together, keyed by the triggering property."),
|
|
12708
|
+
additionalProperties: external_exports.literal(false)
|
|
12709
|
+
}).strict();
|
|
12710
|
+
function countNodes(property) {
|
|
12711
|
+
if (property.type === "object") {
|
|
12712
|
+
const children = Object.keys(property.properties).length;
|
|
12713
|
+
return { leaves: children, nodes: children + 1, instantiated: children };
|
|
12714
|
+
}
|
|
12715
|
+
if (property.type === "array" && property.items.type === "object") {
|
|
12716
|
+
const children = Object.keys(property.items.properties).length;
|
|
12717
|
+
return {
|
|
12718
|
+
leaves: children,
|
|
12719
|
+
nodes: children + 1,
|
|
12720
|
+
instantiated: children * property.maxItems
|
|
12721
|
+
};
|
|
12722
|
+
}
|
|
12723
|
+
return { leaves: 1, nodes: 1, instantiated: 1 };
|
|
12724
|
+
}
|
|
12725
|
+
function childrenOf(property) {
|
|
12726
|
+
if (property.type === "object")
|
|
12727
|
+
return property;
|
|
12728
|
+
if (property.type === "array" && property.items.type === "object")
|
|
12729
|
+
return property.items;
|
|
12730
|
+
return null;
|
|
12731
|
+
}
|
|
12732
|
+
function minimumConfigurationBytes(config) {
|
|
12733
|
+
const rootRequired = new Set(config.required ?? []);
|
|
12734
|
+
let total = 2;
|
|
12735
|
+
for (const [name, property] of Object.entries(config.properties)) {
|
|
12736
|
+
const children = childrenOf(property);
|
|
12737
|
+
if (children === null) {
|
|
12738
|
+
if (!rootRequired.has(name) && declaredLeafDefault(property) === void 0)
|
|
12739
|
+
continue;
|
|
12740
|
+
total += name.length + 3 + minimumLeafBytes(property);
|
|
12741
|
+
continue;
|
|
12742
|
+
}
|
|
12743
|
+
if (!rootRequired.has(name))
|
|
12744
|
+
continue;
|
|
12745
|
+
const inner = minimumGroupBytes(children.properties, children.required ?? []);
|
|
12746
|
+
total += name.length + 3 + (property.type === "array" ? 2 + (property.minItems ?? 0) * inner : inner);
|
|
12747
|
+
}
|
|
12748
|
+
return total;
|
|
12749
|
+
}
|
|
12750
|
+
function minimumGroupBytes(properties, required) {
|
|
12751
|
+
const names = new Set(required);
|
|
12752
|
+
let total = 2;
|
|
12753
|
+
for (const [name, property] of Object.entries(properties)) {
|
|
12754
|
+
if (!names.has(name) && declaredLeafDefault(property) === void 0)
|
|
12755
|
+
continue;
|
|
12756
|
+
total += name.length + 3 + minimumLeafBytes(property);
|
|
12757
|
+
}
|
|
12758
|
+
return total;
|
|
12759
|
+
}
|
|
12760
|
+
function minimumLeafBytes(property) {
|
|
12761
|
+
switch (property.type) {
|
|
12762
|
+
case "string": {
|
|
12763
|
+
const shortestEnum = property.enum?.reduce((a, b) => a.length <= b.length ? a : b);
|
|
12764
|
+
const shortest = shortestEnum?.length ?? Math.max(property.minLength ?? 0, 1);
|
|
12765
|
+
return shortest + 2;
|
|
12766
|
+
}
|
|
12767
|
+
case "integer":
|
|
12768
|
+
case "number":
|
|
12769
|
+
return 1;
|
|
12770
|
+
case "boolean":
|
|
12771
|
+
return 4;
|
|
12772
|
+
case "array":
|
|
12773
|
+
return 2 + (property.minItems ?? 0) * 3;
|
|
12774
|
+
case "object":
|
|
12775
|
+
return 2;
|
|
12776
|
+
}
|
|
12777
|
+
}
|
|
12778
|
+
function declaredLeafDefault(property) {
|
|
12779
|
+
return property.type === "object" ? void 0 : property.default;
|
|
12780
|
+
}
|
|
12781
|
+
var CustomerConfigurationV2Schema = CustomerConfigurationV2ObjectSchema.superRefine((config, ctx) => {
|
|
12782
|
+
const names = Object.keys(config.properties);
|
|
12783
|
+
if (names.length > MAX_CONFIGURATION_PROPERTIES) {
|
|
12784
|
+
ctx.addIssue({
|
|
12785
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12786
|
+
path: ["properties"],
|
|
12787
|
+
message: `A Product may declare at most ${MAX_CONFIGURATION_PROPERTIES} customer settings; found ${names.length}.`
|
|
12788
|
+
});
|
|
12789
|
+
}
|
|
12790
|
+
let leaves = 0;
|
|
12791
|
+
let nodes = 0;
|
|
12792
|
+
let instantiated = 0;
|
|
12793
|
+
for (const name of names) {
|
|
12794
|
+
const property = config.properties[name];
|
|
12795
|
+
const path = ["properties", name];
|
|
12796
|
+
const counted = countNodes(property);
|
|
12797
|
+
leaves += counted.leaves;
|
|
12798
|
+
nodes += counted.nodes;
|
|
12799
|
+
instantiated += counted.instantiated;
|
|
12800
|
+
const children = childrenOf(property);
|
|
12801
|
+
if (children === null) {
|
|
12802
|
+
checkDeclaredProperty(name, property, path, ctx, true);
|
|
12803
|
+
continue;
|
|
12804
|
+
}
|
|
12805
|
+
const infrastructure = infrastructureVocabularyViolation(name);
|
|
12806
|
+
if (infrastructure) {
|
|
12807
|
+
ctx.addIssue({
|
|
12808
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12809
|
+
path,
|
|
12810
|
+
message: `${infrastructure}. Customer settings describe outcomes, not infrastructure.`
|
|
12811
|
+
});
|
|
12812
|
+
}
|
|
12813
|
+
const platformOwned = platformOwnedFieldViolation(name);
|
|
12814
|
+
if (platformOwned) {
|
|
12815
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message: `${platformOwned}.` });
|
|
12816
|
+
}
|
|
12817
|
+
const childNames = Object.keys(children.properties);
|
|
12818
|
+
if (childNames.length === 0) {
|
|
12819
|
+
ctx.addIssue({
|
|
12820
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12821
|
+
path: [...path, "properties"],
|
|
12822
|
+
message: `"${name}" declares no settings. A group with nothing in it renders as an empty section.`
|
|
12823
|
+
});
|
|
12824
|
+
}
|
|
12825
|
+
if (childNames.length > MAX_CONFIGURATION_PROPERTIES) {
|
|
12826
|
+
ctx.addIssue({
|
|
12827
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12828
|
+
path: [...path, "properties"],
|
|
12829
|
+
message: `"${name}" may declare at most ${MAX_CONFIGURATION_PROPERTIES} settings; found ${childNames.length}.`
|
|
12830
|
+
});
|
|
12831
|
+
}
|
|
12832
|
+
if (property.type === "array" && property.default !== void 0) {
|
|
12833
|
+
ctx.addIssue({
|
|
12834
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12835
|
+
path: [...path, "default"],
|
|
12836
|
+
message: `"${name}" is a list of groups and cannot declare a default. Declare defaults on the settings inside it.`
|
|
12837
|
+
});
|
|
12838
|
+
}
|
|
12839
|
+
if (property.type === "array" && property.minItems !== void 0 && property.minItems > property.maxItems) {
|
|
12840
|
+
ctx.addIssue({
|
|
12841
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12842
|
+
path,
|
|
12843
|
+
message: `"${name}" has minItems greater than maxItems.`
|
|
12844
|
+
});
|
|
12845
|
+
}
|
|
12846
|
+
for (const childName of childNames) {
|
|
12847
|
+
checkDeclaredProperty(childName, children.properties[childName], [...path, "properties", childName], ctx, false);
|
|
12848
|
+
}
|
|
12849
|
+
for (const required of children.required ?? []) {
|
|
12850
|
+
if (!Object.hasOwn(children.properties, required)) {
|
|
12851
|
+
ctx.addIssue({
|
|
12852
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12853
|
+
path: [...path, "required"],
|
|
12854
|
+
message: `"${required}" is listed as required in "${name}" but is not one of its settings.`
|
|
12855
|
+
});
|
|
12856
|
+
}
|
|
12857
|
+
}
|
|
12858
|
+
}
|
|
12859
|
+
if (leaves > MAX_CONFIGURATION_LEAVES) {
|
|
12860
|
+
ctx.addIssue({
|
|
12861
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12862
|
+
path: ["properties"],
|
|
12863
|
+
message: `A Product may declare at most ${MAX_CONFIGURATION_LEAVES} customer settings in total; found ${leaves}.`
|
|
12864
|
+
});
|
|
12865
|
+
}
|
|
12866
|
+
if (nodes > MAX_CONFIGURATION_NODES) {
|
|
12867
|
+
ctx.addIssue({
|
|
12868
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12869
|
+
path: ["properties"],
|
|
12870
|
+
message: `A Product may declare at most ${MAX_CONFIGURATION_NODES} configuration nodes; found ${nodes}.`
|
|
12871
|
+
});
|
|
12872
|
+
}
|
|
12873
|
+
if (instantiated > MAX_CONFIGURATION_VALUE_LEAVES) {
|
|
12874
|
+
ctx.addIssue({
|
|
12875
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12876
|
+
path: ["properties"],
|
|
12877
|
+
message: `This Product's settings could expand to ${instantiated} values \u2014 a list of groups instantiates its settings once per item. At most ${MAX_CONFIGURATION_VALUE_LEAVES} are allowed; reduce maxItems, or the number of settings inside the list.`
|
|
12878
|
+
});
|
|
12879
|
+
}
|
|
12880
|
+
for (const name of config.required ?? []) {
|
|
12881
|
+
if (!Object.hasOwn(config.properties, name)) {
|
|
12882
|
+
ctx.addIssue({
|
|
12883
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12884
|
+
path: ["required"],
|
|
12885
|
+
message: `"${name}" is listed as required but is not a declared property.`
|
|
12886
|
+
});
|
|
12887
|
+
}
|
|
12888
|
+
}
|
|
12889
|
+
const floor = minimumConfigurationBytes(config);
|
|
12890
|
+
if (floor > MAX_CONFIGURATION_VALUE_BYTES) {
|
|
12891
|
+
ctx.addIssue({
|
|
12892
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12893
|
+
path: ["properties"],
|
|
12894
|
+
message: `The smallest configuration that could satisfy this Product is at least ${floor} bytes, and the limit is ${MAX_CONFIGURATION_VALUE_BYTES}. No customer could deploy it \u2014 reduce the required settings, their minimum lengths, or a list's minItems.`
|
|
12895
|
+
});
|
|
12896
|
+
}
|
|
12897
|
+
checkDependentRequired(config, ctx);
|
|
12898
|
+
checkOneSecretPerGroup(config, ctx);
|
|
12899
|
+
});
|
|
12900
|
+
function enumerableValues(property) {
|
|
12901
|
+
const out = [];
|
|
12902
|
+
if (property.type === "string") {
|
|
12903
|
+
if (property.enum)
|
|
12904
|
+
out.push(["enum", property.enum]);
|
|
12905
|
+
if (property.default !== void 0)
|
|
12906
|
+
out.push(["default", [property.default]]);
|
|
12907
|
+
}
|
|
12908
|
+
if (property.type === "array") {
|
|
12909
|
+
if (property.items.enum)
|
|
12910
|
+
out.push(["items", property.items.enum]);
|
|
12911
|
+
if (property.default)
|
|
12912
|
+
out.push(["default", property.default]);
|
|
12913
|
+
}
|
|
12914
|
+
return out;
|
|
12915
|
+
}
|
|
12916
|
+
function isSafeRegex(pattern) {
|
|
12917
|
+
try {
|
|
12918
|
+
new RegExp(pattern);
|
|
12919
|
+
return true;
|
|
12920
|
+
} catch {
|
|
12921
|
+
return false;
|
|
12922
|
+
}
|
|
12923
|
+
}
|
|
12924
|
+
function isSecretProperty(property) {
|
|
12925
|
+
return property.type === "string" && property["x-secret"] === true;
|
|
12926
|
+
}
|
|
12927
|
+
|
|
12928
|
+
// ../product-configuration/dist/configuration-path.js
|
|
12929
|
+
var MAX_CONFIGURATION_PATH_SEGMENTS = MAX_CONFIGURATION_DEPTH + 1;
|
|
12930
|
+
function isIndexSegment(raw) {
|
|
12931
|
+
return /^\d+$/.test(raw) && String(Number(raw)) === raw;
|
|
12932
|
+
}
|
|
12933
|
+
function isPathSegment(segment) {
|
|
12934
|
+
if (typeof segment === "number")
|
|
12935
|
+
return Number.isInteger(segment) && segment >= 0;
|
|
12936
|
+
return CONFIGURATION_PROPERTY_NAME_REGEX.test(segment) || isIndexSegment(segment);
|
|
12937
|
+
}
|
|
12938
|
+
function configurationPath(...segments) {
|
|
12939
|
+
if (segments.length === 0 || segments.length > MAX_CONFIGURATION_PATH_SEGMENTS)
|
|
12940
|
+
return null;
|
|
12941
|
+
if (!segments.every(isPathSegment))
|
|
12942
|
+
return null;
|
|
12943
|
+
if (typeof segments[0] === "number" || isIndexSegment(String(segments[0])))
|
|
12944
|
+
return null;
|
|
12945
|
+
if (segments.length === 1)
|
|
12946
|
+
return String(segments[0]);
|
|
12947
|
+
return `/${segments.map(String).join("/")}`;
|
|
12948
|
+
}
|
|
12949
|
+
function parseConfigurationPath(raw) {
|
|
12950
|
+
if (typeof raw !== "string" || raw.length === 0)
|
|
12951
|
+
return null;
|
|
12952
|
+
if (!raw.startsWith("/"))
|
|
12953
|
+
return configurationPath(raw);
|
|
12954
|
+
const segments = raw.slice(1).split("/");
|
|
12955
|
+
if (segments.length < 2)
|
|
12956
|
+
return null;
|
|
12957
|
+
return configurationPath(...segments);
|
|
12958
|
+
}
|
|
12959
|
+
function pathSegments(path) {
|
|
12960
|
+
const raw = path.startsWith("/") ? path.slice(1).split("/") : [path];
|
|
12961
|
+
return raw.map((segment) => isIndexSegment(segment) ? Number(segment) : segment);
|
|
12962
|
+
}
|
|
12963
|
+
function declarationPathOf(path) {
|
|
12964
|
+
const segments = pathSegments(path).filter((segment) => typeof segment !== "number");
|
|
12965
|
+
return configurationPath(...segments) ?? path;
|
|
12966
|
+
}
|
|
12967
|
+
function printableConfigurationPath(path) {
|
|
12968
|
+
return pathSegments(path).join(".");
|
|
12969
|
+
}
|
|
12970
|
+
|
|
12971
|
+
// ../product-configuration/dist/canonical-json.js
|
|
12972
|
+
function canonicalise(value, path) {
|
|
12973
|
+
if (value === null)
|
|
12974
|
+
return "null";
|
|
12975
|
+
if (typeof value === "string")
|
|
12976
|
+
return JSON.stringify(value);
|
|
12977
|
+
if (typeof value === "boolean")
|
|
12978
|
+
return value ? "true" : "false";
|
|
12979
|
+
if (typeof value === "number") {
|
|
12980
|
+
if (!Number.isFinite(value)) {
|
|
12981
|
+
throw new Error(`canonicalJson: non-finite number at ${path}`);
|
|
12982
|
+
}
|
|
12983
|
+
return JSON.stringify(value === 0 ? 0 : value);
|
|
12984
|
+
}
|
|
12985
|
+
if (typeof value !== "object") {
|
|
12986
|
+
throw new Error(`canonicalJson: ${typeof value} is not JSON at ${path}`);
|
|
12987
|
+
}
|
|
12988
|
+
if (Array.isArray(value)) {
|
|
12989
|
+
return `[${value.map((item, i) => canonicalise(item, `${path}[${i}]`)).join(",")}]`;
|
|
12990
|
+
}
|
|
12991
|
+
const entries = Object.entries(value);
|
|
12992
|
+
for (const [key, item] of entries) {
|
|
12993
|
+
if (item === void 0) {
|
|
12994
|
+
throw new Error(`canonicalJson: undefined property at ${path}.${key}`);
|
|
12995
|
+
}
|
|
12996
|
+
}
|
|
12997
|
+
const sorted = entries.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
12998
|
+
const body = sorted.map(([key, item]) => `${JSON.stringify(key)}:${canonicalise(item, `${path}.${key}`)}`).join(",");
|
|
12999
|
+
return `{${body}}`;
|
|
13000
|
+
}
|
|
13001
|
+
function canonicalJson(value) {
|
|
13002
|
+
return canonicalise(value, "$");
|
|
13003
|
+
}
|
|
13004
|
+
|
|
13005
|
+
// ../product-configuration/dist/configuration-tree.js
|
|
13006
|
+
function containerChildren(property) {
|
|
13007
|
+
if (property.type === "object" && property.properties !== void 0) {
|
|
13008
|
+
return {
|
|
13009
|
+
kind: "object",
|
|
13010
|
+
properties: property.properties,
|
|
13011
|
+
required: property.required ?? []
|
|
13012
|
+
};
|
|
13013
|
+
}
|
|
13014
|
+
if (property.type === "array" && property.items !== void 0) {
|
|
13015
|
+
const items = property.items;
|
|
13016
|
+
if (items.type !== "object" || items.properties === void 0)
|
|
13017
|
+
return null;
|
|
13018
|
+
return {
|
|
13019
|
+
kind: "array",
|
|
13020
|
+
properties: items.properties,
|
|
13021
|
+
required: items.required ?? []
|
|
13022
|
+
};
|
|
13023
|
+
}
|
|
13024
|
+
return null;
|
|
13025
|
+
}
|
|
13026
|
+
function isConfigurationContainer(property) {
|
|
13027
|
+
return containerChildren(property) !== null;
|
|
13028
|
+
}
|
|
13029
|
+
function configurationLeaves(schema) {
|
|
13030
|
+
const out = [];
|
|
13031
|
+
for (const [name, property] of Object.entries(schema.properties)) {
|
|
13032
|
+
const children = containerChildren(property);
|
|
13033
|
+
if (children === null) {
|
|
13034
|
+
const path = configurationPath(name);
|
|
13035
|
+
if (path !== null) {
|
|
13036
|
+
out.push({ path, name, property, container: null });
|
|
13037
|
+
}
|
|
13038
|
+
continue;
|
|
13039
|
+
}
|
|
13040
|
+
const containerPath = configurationPath(name);
|
|
13041
|
+
if (containerPath === null)
|
|
12628
13042
|
continue;
|
|
12629
|
-
|
|
12630
|
-
|
|
12631
|
-
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
|
|
12635
|
-
}
|
|
13043
|
+
const container = {
|
|
13044
|
+
path: containerPath,
|
|
13045
|
+
name,
|
|
13046
|
+
kind: children.kind,
|
|
13047
|
+
property,
|
|
13048
|
+
required: children.required
|
|
13049
|
+
};
|
|
13050
|
+
for (const [childName, child] of Object.entries(children.properties)) {
|
|
13051
|
+
const path = configurationPath(name, childName);
|
|
13052
|
+
if (path === null)
|
|
13053
|
+
continue;
|
|
13054
|
+
out.push({ path, name: childName, property: child, container });
|
|
13055
|
+
}
|
|
12636
13056
|
}
|
|
13057
|
+
return out;
|
|
12637
13058
|
}
|
|
12638
|
-
function
|
|
13059
|
+
function configurationContainers(schema) {
|
|
12639
13060
|
const out = [];
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
13061
|
+
for (const [name, property] of Object.entries(schema.properties)) {
|
|
13062
|
+
const children = containerChildren(property);
|
|
13063
|
+
if (children === null)
|
|
13064
|
+
continue;
|
|
13065
|
+
const path = configurationPath(name);
|
|
13066
|
+
if (path === null)
|
|
13067
|
+
continue;
|
|
13068
|
+
out.push({
|
|
13069
|
+
path,
|
|
13070
|
+
name,
|
|
13071
|
+
kind: children.kind,
|
|
13072
|
+
property,
|
|
13073
|
+
required: children.required
|
|
13074
|
+
});
|
|
12651
13075
|
}
|
|
12652
13076
|
return out;
|
|
12653
13077
|
}
|
|
12654
|
-
function
|
|
12655
|
-
|
|
12656
|
-
|
|
13078
|
+
function leafAt(schema, path) {
|
|
13079
|
+
const declaration = declarationPathOf(path);
|
|
13080
|
+
return configurationLeaves(schema).find((leaf) => leaf.path === declaration) ?? null;
|
|
13081
|
+
}
|
|
13082
|
+
function declaresPath(schema, path) {
|
|
13083
|
+
if (leafAt(schema, path) !== null)
|
|
12657
13084
|
return true;
|
|
12658
|
-
|
|
12659
|
-
return false;
|
|
12660
|
-
}
|
|
13085
|
+
return configurationContainers(schema).some((container) => container.path === declarationPathOf(path));
|
|
12661
13086
|
}
|
|
12662
13087
|
|
|
12663
13088
|
// ../product-configuration/dist/customer-configuration-input.js
|
|
@@ -12666,11 +13091,24 @@ var MAX_REPORTED_UNDECLARED_KEYS = 10;
|
|
|
12666
13091
|
function isPlainObject(value) {
|
|
12667
13092
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12668
13093
|
}
|
|
12669
|
-
function
|
|
12670
|
-
|
|
13094
|
+
function report(walk, field, message) {
|
|
13095
|
+
if (walk.issues.length >= MAX_CONFIGURATION_ISSUES) {
|
|
13096
|
+
walk.suppressed += 1;
|
|
13097
|
+
return;
|
|
13098
|
+
}
|
|
13099
|
+
walk.issues.push({ field, message });
|
|
13100
|
+
}
|
|
13101
|
+
function drain(walk, collected) {
|
|
13102
|
+
for (const issue of collected)
|
|
13103
|
+
report(walk, issue.field, issue.message);
|
|
12671
13104
|
}
|
|
12672
13105
|
function validateSubmittedConfiguration(schema, submitted, presence = {}) {
|
|
12673
|
-
const
|
|
13106
|
+
const walk = {
|
|
13107
|
+
issues: [],
|
|
13108
|
+
suppressed: 0,
|
|
13109
|
+
leaves: 0,
|
|
13110
|
+
referenced: new Set(presence.referenced ?? [])
|
|
13111
|
+
};
|
|
12674
13112
|
const supplied = /* @__PURE__ */ new Set();
|
|
12675
13113
|
if (submitted !== void 0 && submitted !== null && !isPlainObject(submitted)) {
|
|
12676
13114
|
return {
|
|
@@ -12680,64 +13118,195 @@ function validateSubmittedConfiguration(schema, submitted, presence = {}) {
|
|
|
12680
13118
|
};
|
|
12681
13119
|
}
|
|
12682
13120
|
const input = isPlainObject(submitted) ? submitted : {};
|
|
12683
|
-
const
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
|
|
12688
|
-
});
|
|
12689
|
-
}
|
|
12690
|
-
if (undeclared.length > MAX_REPORTED_UNDECLARED_KEYS) {
|
|
12691
|
-
issues.push({
|
|
13121
|
+
const secrets = {};
|
|
13122
|
+
const configuration = validateObject({ properties: schema.properties, required: schema.required }, input, null, walk, { secrets, supplied });
|
|
13123
|
+
drain(walk, crossFieldIssues(schema, supplied, presence));
|
|
13124
|
+
if (walk.suppressed > 0) {
|
|
13125
|
+
walk.issues.push({
|
|
12692
13126
|
field: "",
|
|
12693
|
-
|
|
12694
|
-
// cannot carry anything the caller chose.
|
|
12695
|
-
message: `${undeclared.length - MAX_REPORTED_UNDECLARED_KEYS} further settings are not declared by this Product.`
|
|
13127
|
+
message: `${walk.suppressed} further problems were found and are not listed.`
|
|
12696
13128
|
});
|
|
12697
13129
|
}
|
|
12698
|
-
|
|
12699
|
-
|
|
12700
|
-
|
|
12701
|
-
|
|
12702
|
-
|
|
12703
|
-
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
13130
|
+
if (declaresContainer(schema)) {
|
|
13131
|
+
const size = utf8ByteLength(JSON.stringify(configuration));
|
|
13132
|
+
if (size > MAX_CONFIGURATION_VALUE_BYTES) {
|
|
13133
|
+
report(walk, "", `This configuration is ${size} bytes once defaults are applied, and the limit is ${MAX_CONFIGURATION_VALUE_BYTES}. Remove some items.`);
|
|
13134
|
+
}
|
|
13135
|
+
}
|
|
13136
|
+
if (walk.issues.length > 0)
|
|
13137
|
+
return { ok: false, issues: walk.issues, partial: configuration };
|
|
13138
|
+
return { ok: true, configuration, secrets };
|
|
13139
|
+
}
|
|
13140
|
+
function utf8ByteLength(value) {
|
|
13141
|
+
return new TextEncoder().encode(value).length;
|
|
13142
|
+
}
|
|
13143
|
+
function declaresContainer(schema) {
|
|
13144
|
+
return Object.values(schema.properties).some((property) => isConfigurationContainer(property));
|
|
13145
|
+
}
|
|
13146
|
+
function containsReferenced(walk, container) {
|
|
13147
|
+
if (walk.referenced.size === 0)
|
|
13148
|
+
return false;
|
|
13149
|
+
const parsedOuter = parseConfigurationPath(container);
|
|
13150
|
+
if (parsedOuter === null)
|
|
13151
|
+
return false;
|
|
13152
|
+
const outer = pathSegments(parsedOuter);
|
|
13153
|
+
for (const candidate of walk.referenced) {
|
|
13154
|
+
const parsed = parseConfigurationPath(candidate);
|
|
13155
|
+
if (parsed === null)
|
|
13156
|
+
continue;
|
|
13157
|
+
const inner = pathSegments(parsed);
|
|
13158
|
+
if (inner.length <= outer.length)
|
|
13159
|
+
continue;
|
|
13160
|
+
if (outer.every((segment, index) => inner[index] === segment))
|
|
13161
|
+
return true;
|
|
13162
|
+
}
|
|
13163
|
+
return false;
|
|
13164
|
+
}
|
|
13165
|
+
function validateObject(declaration, input, container, walk, root) {
|
|
13166
|
+
const required = new Set(declaration.required ?? []);
|
|
13167
|
+
const out = {};
|
|
13168
|
+
const fieldFor = (name) => {
|
|
13169
|
+
const path = container === null ? configurationPath(name) : configurationPath(...pathSegments(container), name);
|
|
13170
|
+
return path ?? "";
|
|
13171
|
+
};
|
|
13172
|
+
const undeclared = Object.keys(input).filter((name) => !Object.hasOwn(declaration.properties, name));
|
|
13173
|
+
for (const name of undeclared.slice(0, MAX_REPORTED_UNDECLARED_KEYS)) {
|
|
13174
|
+
report(walk, fieldFor(name), "This Product does not declare a setting with that name.");
|
|
13175
|
+
}
|
|
13176
|
+
if (undeclared.length > MAX_REPORTED_UNDECLARED_KEYS) {
|
|
13177
|
+
report(walk, container === null ? "" : container, `${undeclared.length - MAX_REPORTED_UNDECLARED_KEYS} further settings are not declared by this Product.`);
|
|
13178
|
+
}
|
|
13179
|
+
for (const [name, property] of Object.entries(declaration.properties)) {
|
|
13180
|
+
const field = fieldFor(name);
|
|
13181
|
+
const children = containerDeclaration(property);
|
|
13182
|
+
if (children !== null) {
|
|
13183
|
+
const value = input[name];
|
|
13184
|
+
const filled = validateContainer(name, property, children, value, field, walk);
|
|
13185
|
+
if (filled !== void 0)
|
|
13186
|
+
out[name] = filled;
|
|
13187
|
+
else if (required.has(name) && !containsReferenced(walk, field))
|
|
13188
|
+
report(walk, field, "This setting is required.");
|
|
13189
|
+
continue;
|
|
13190
|
+
}
|
|
13191
|
+
const leaf = property;
|
|
13192
|
+
if (walk.referenced.has(field)) {
|
|
13193
|
+
const sent = input[name];
|
|
13194
|
+
if (Object.hasOwn(input, name) && sent !== void 0) {
|
|
13195
|
+
report(walk, field, "This setting is answered by another Resource, so it cannot also be set here.");
|
|
13196
|
+
}
|
|
13197
|
+
continue;
|
|
13198
|
+
}
|
|
13199
|
+
const raw = input[name];
|
|
13200
|
+
const blank = typeof raw === "string" && raw.trim().length === 0;
|
|
13201
|
+
const present = Object.hasOwn(input, name) && raw !== void 0 && !blank;
|
|
13202
|
+
const secret = root !== null && isSecretProperty(leaf);
|
|
13203
|
+
if (present && root !== null && container === null)
|
|
13204
|
+
root.supplied.add(name);
|
|
12707
13205
|
if (!present) {
|
|
12708
|
-
const fallback = secret ? void 0 : defaultOf(
|
|
13206
|
+
const fallback = secret ? void 0 : defaultOf(leaf);
|
|
12709
13207
|
if (fallback !== void 0) {
|
|
12710
|
-
|
|
13208
|
+
walk.leaves += 1;
|
|
13209
|
+
out[name] = fallback;
|
|
12711
13210
|
} else if (required.has(name)) {
|
|
12712
|
-
|
|
13211
|
+
report(walk, field, "This setting is required.");
|
|
12713
13212
|
}
|
|
12714
13213
|
continue;
|
|
12715
13214
|
}
|
|
12716
|
-
|
|
12717
|
-
const
|
|
12718
|
-
const checked = checkProperty(
|
|
12719
|
-
if (
|
|
13215
|
+
walk.leaves += 1;
|
|
13216
|
+
const collected = [];
|
|
13217
|
+
const checked = checkProperty(field, leaf, raw, collected);
|
|
13218
|
+
if (collected.length > 0 || checked === void 0) {
|
|
13219
|
+
drain(walk, collected);
|
|
12720
13220
|
continue;
|
|
13221
|
+
}
|
|
12721
13222
|
if (secret) {
|
|
12722
13223
|
if (typeof checked === "string" && checked.length > 0)
|
|
12723
|
-
secrets[name] = checked;
|
|
12724
|
-
else if (required.has(name))
|
|
12725
|
-
|
|
12726
|
-
}
|
|
13224
|
+
root.secrets[name] = checked;
|
|
13225
|
+
else if (required.has(name))
|
|
13226
|
+
report(walk, field, "This setting is required.");
|
|
12727
13227
|
continue;
|
|
12728
13228
|
}
|
|
12729
|
-
|
|
13229
|
+
out[name] = checked;
|
|
12730
13230
|
}
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
|
|
13231
|
+
return out;
|
|
13232
|
+
}
|
|
13233
|
+
function containerDeclaration(property) {
|
|
13234
|
+
if (property.type === "object" && property.properties !== void 0) {
|
|
13235
|
+
return {
|
|
13236
|
+
kind: "object",
|
|
13237
|
+
properties: property.properties,
|
|
13238
|
+
required: property.required,
|
|
13239
|
+
maxItems: 1
|
|
13240
|
+
};
|
|
13241
|
+
}
|
|
13242
|
+
if (property.type === "array" && property.items !== void 0) {
|
|
13243
|
+
const items = property.items;
|
|
13244
|
+
if (items.type !== "object" || items.properties === void 0)
|
|
13245
|
+
return null;
|
|
13246
|
+
return {
|
|
13247
|
+
kind: "array",
|
|
13248
|
+
properties: items.properties,
|
|
13249
|
+
required: items.required,
|
|
13250
|
+
maxItems: property.maxItems ?? 0,
|
|
13251
|
+
minItems: property.minItems,
|
|
13252
|
+
uniqueItems: property.uniqueItems === true
|
|
13253
|
+
};
|
|
13254
|
+
}
|
|
13255
|
+
return null;
|
|
13256
|
+
}
|
|
13257
|
+
function validateContainer(name, property, children, value, field, walk) {
|
|
13258
|
+
const path = parseConfigurationPath(field);
|
|
13259
|
+
if (children.kind === "object") {
|
|
13260
|
+
if (value === void 0)
|
|
13261
|
+
return void 0;
|
|
13262
|
+
if (!isPlainObject(value)) {
|
|
13263
|
+
report(walk, field, "Expected a group of settings.");
|
|
13264
|
+
return void 0;
|
|
13265
|
+
}
|
|
13266
|
+
const filled = validateObject(children, value, path, walk, null);
|
|
13267
|
+
return Object.keys(filled).length === 0 ? void 0 : filled;
|
|
13268
|
+
}
|
|
13269
|
+
if (value === void 0)
|
|
13270
|
+
return void 0;
|
|
13271
|
+
if (!Array.isArray(value)) {
|
|
13272
|
+
report(walk, field, "Expected a list.");
|
|
13273
|
+
return void 0;
|
|
13274
|
+
}
|
|
13275
|
+
if (value.length > children.maxItems) {
|
|
13276
|
+
report(walk, field, `At most ${children.maxItems} items are allowed.`);
|
|
13277
|
+
return void 0;
|
|
13278
|
+
}
|
|
13279
|
+
if (children.minItems !== void 0 && value.length < children.minItems) {
|
|
13280
|
+
report(walk, field, `At least ${children.minItems} items are required.`);
|
|
13281
|
+
return void 0;
|
|
13282
|
+
}
|
|
13283
|
+
const out = [];
|
|
13284
|
+
for (const [index, element] of value.entries()) {
|
|
13285
|
+
if (walk.leaves >= MAX_CONFIGURATION_VALUE_LEAVES) {
|
|
13286
|
+
report(walk, field, "This configuration has too many values.");
|
|
13287
|
+
break;
|
|
13288
|
+
}
|
|
13289
|
+
if (!isPlainObject(element)) {
|
|
13290
|
+
report(walk, `${field}`, `Item ${index + 1} is not a group of settings.`);
|
|
13291
|
+
continue;
|
|
13292
|
+
}
|
|
13293
|
+
const elementPath = path === null ? null : configurationPath(...pathSegments(path), index);
|
|
13294
|
+
out.push(validateObject(children, element, elementPath, walk, null));
|
|
13295
|
+
}
|
|
13296
|
+
if (children.uniqueItems === true) {
|
|
13297
|
+
const seen = new Set(out.map((entry) => canonicalJson(entry)));
|
|
13298
|
+
if (seen.size !== out.length) {
|
|
13299
|
+
report(walk, field, "Items must be unique.");
|
|
13300
|
+
return void 0;
|
|
13301
|
+
}
|
|
13302
|
+
}
|
|
13303
|
+
return out;
|
|
12735
13304
|
}
|
|
12736
13305
|
function crossFieldIssues(schema, supplied, presence) {
|
|
12737
13306
|
const clauses = Object.entries(schema.dependentRequired ?? {});
|
|
12738
13307
|
if (clauses.length === 0)
|
|
12739
13308
|
return [];
|
|
12740
|
-
const alsoPresent = new Set(presence.present ?? []);
|
|
13309
|
+
const alsoPresent = /* @__PURE__ */ new Set([...presence.present ?? [], ...presence.referenced ?? []]);
|
|
12741
13310
|
const unknown = new Set(presence.unknown ?? []);
|
|
12742
13311
|
const known = (name) => !unknown.has(name);
|
|
12743
13312
|
const held = (name) => supplied.has(name) || alsoPresent.has(name);
|
|
@@ -12905,11 +13474,11 @@ var RESOURCE_KEY_RULE = "A resource key is 3\u201363 characters of lowercase let
|
|
|
12905
13474
|
var ResourceKeySchema = external_exports.string().regex(RESOURCE_KEY_PATTERN, RESOURCE_KEY_RULE).describe(RESOURCE_KEY_RULE);
|
|
12906
13475
|
|
|
12907
13476
|
// ../product-configuration/dist/product-instance-example.js
|
|
12908
|
-
function resolveExampleChoice(options, selected,
|
|
13477
|
+
function resolveExampleChoice(options, selected, declaredDefault2) {
|
|
12909
13478
|
if (selected !== void 0)
|
|
12910
13479
|
return options.includes(selected) ? { value: selected, issue: null } : { value: null, issue: "invalid" };
|
|
12911
|
-
if (
|
|
12912
|
-
return { value:
|
|
13480
|
+
if (declaredDefault2 !== void 0 && options.includes(declaredDefault2))
|
|
13481
|
+
return { value: declaredDefault2, issue: null };
|
|
12913
13482
|
if (options.length === 1)
|
|
12914
13483
|
return { value: options[0], issue: null };
|
|
12915
13484
|
return { value: null, issue: options.length === 0 ? "unavailable" : "required" };
|
|
@@ -12937,17 +13506,84 @@ function seedConfiguration(configuration) {
|
|
|
12937
13506
|
requiredSecrets.push(name);
|
|
12938
13507
|
continue;
|
|
12939
13508
|
}
|
|
13509
|
+
const children = containerChildren2(declaration);
|
|
13510
|
+
if (children !== null) {
|
|
13511
|
+
if (!required.has(name))
|
|
13512
|
+
continue;
|
|
13513
|
+
if (children.kind === "object") {
|
|
13514
|
+
values[name] = seedGroup(children, name, open);
|
|
13515
|
+
continue;
|
|
13516
|
+
}
|
|
13517
|
+
const count = children.minItems ?? 0;
|
|
13518
|
+
values[name] = Array.from({ length: count }, () => seedGroup(children, name, open));
|
|
13519
|
+
if (count > 1)
|
|
13520
|
+
dedupeOpen(open);
|
|
13521
|
+
continue;
|
|
13522
|
+
}
|
|
12940
13523
|
if (declaration.default !== void 0) {
|
|
12941
13524
|
values[name] = declaration.default;
|
|
12942
13525
|
continue;
|
|
12943
13526
|
}
|
|
12944
13527
|
if (required.has(name)) {
|
|
12945
13528
|
values[name] = "";
|
|
12946
|
-
open.push({ name, type: declaration.type ?? null });
|
|
13529
|
+
open.push({ name, label: name, type: declaration.type ?? null });
|
|
12947
13530
|
}
|
|
12948
13531
|
}
|
|
12949
13532
|
return { values, open, requiredSecrets, groups };
|
|
12950
13533
|
}
|
|
13534
|
+
function containerChildren2(declaration) {
|
|
13535
|
+
const node = declaration;
|
|
13536
|
+
if (node.type === "object" && node.properties !== void 0) {
|
|
13537
|
+
return {
|
|
13538
|
+
kind: "object",
|
|
13539
|
+
properties: node.properties,
|
|
13540
|
+
required: node.required ?? []
|
|
13541
|
+
};
|
|
13542
|
+
}
|
|
13543
|
+
if (node.type === "array" && node.items !== void 0) {
|
|
13544
|
+
const items = node.items;
|
|
13545
|
+
if (items.type !== "object" || items.properties === void 0)
|
|
13546
|
+
return null;
|
|
13547
|
+
return {
|
|
13548
|
+
kind: "array",
|
|
13549
|
+
properties: items.properties,
|
|
13550
|
+
required: items.required ?? [],
|
|
13551
|
+
...typeof node.minItems === "number" ? { minItems: node.minItems } : {}
|
|
13552
|
+
};
|
|
13553
|
+
}
|
|
13554
|
+
return null;
|
|
13555
|
+
}
|
|
13556
|
+
function dedupeOpen(open) {
|
|
13557
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13558
|
+
const unique = open.filter((entry) => {
|
|
13559
|
+
if (seen.has(entry.name))
|
|
13560
|
+
return false;
|
|
13561
|
+
seen.add(entry.name);
|
|
13562
|
+
return true;
|
|
13563
|
+
});
|
|
13564
|
+
open.length = 0;
|
|
13565
|
+
open.push(...unique);
|
|
13566
|
+
}
|
|
13567
|
+
function seedGroup(children, container, open) {
|
|
13568
|
+
const required = new Set(children.required);
|
|
13569
|
+
const values = {};
|
|
13570
|
+
for (const [name, declaration] of Object.entries(children.properties)) {
|
|
13571
|
+
if (declaration.default !== void 0) {
|
|
13572
|
+
values[name] = declaration.default;
|
|
13573
|
+
continue;
|
|
13574
|
+
}
|
|
13575
|
+
if (required.has(name)) {
|
|
13576
|
+
values[name] = "";
|
|
13577
|
+
const path = configurationPath(container, name);
|
|
13578
|
+
open.push({
|
|
13579
|
+
name: path ?? name,
|
|
13580
|
+
label: path === null ? name : printableConfigurationPath(path),
|
|
13581
|
+
type: declaration.type ?? null
|
|
13582
|
+
});
|
|
13583
|
+
}
|
|
13584
|
+
}
|
|
13585
|
+
return values;
|
|
13586
|
+
}
|
|
12951
13587
|
function productInstanceExample(input) {
|
|
12952
13588
|
return {
|
|
12953
13589
|
apiVersion: RESOURCE_API_VERSION,
|
|
@@ -13059,13 +13695,32 @@ var OperationStatusSchema = external_exports.enum([
|
|
|
13059
13695
|
|
|
13060
13696
|
// ../product-contracts/dist/api-version.js
|
|
13061
13697
|
var PRODUCT_API_VERSION = "products.vardeflyt.no/v1";
|
|
13698
|
+
var PRODUCT_API_VERSION_V2 = "products.vardeflyt.no/v2";
|
|
13699
|
+
var PARSEABLE_PRODUCT_API_VERSIONS = /* @__PURE__ */ new Set([
|
|
13700
|
+
PRODUCT_API_VERSION,
|
|
13701
|
+
PRODUCT_API_VERSION_V2
|
|
13702
|
+
]);
|
|
13703
|
+
function supportedList() {
|
|
13704
|
+
return [...PARSEABLE_PRODUCT_API_VERSIONS].map((value) => `"${value}"`).join(" or ");
|
|
13705
|
+
}
|
|
13706
|
+
function unsupportedProductApiVersionMessage() {
|
|
13707
|
+
return `apiVersion must be ${supportedList()}. An unrecognized contract format is refused rather than ignored.`;
|
|
13708
|
+
}
|
|
13062
13709
|
var PRODUCT_DEFINITION_KIND = "ProductDefinition";
|
|
13063
13710
|
var DEPLOYMENT_BLUEPRINT_KIND = "DeploymentBlueprint";
|
|
13064
13711
|
var ProductApiVersionSchema = external_exports.literal(PRODUCT_API_VERSION, {
|
|
13065
13712
|
errorMap: () => ({
|
|
13066
|
-
message: `apiVersion must be
|
|
13713
|
+
message: `apiVersion must be ${supportedList()}. An unrecognized contract format is refused rather than ignored.`
|
|
13714
|
+
})
|
|
13715
|
+
});
|
|
13716
|
+
var ProductApiVersionV2Schema = external_exports.literal(PRODUCT_API_VERSION_V2, {
|
|
13717
|
+
errorMap: () => ({
|
|
13718
|
+
message: `apiVersion must be ${supportedList()}. An unrecognized contract format is refused rather than ignored.`
|
|
13067
13719
|
})
|
|
13068
13720
|
});
|
|
13721
|
+
var ProductApiVersionAnySchema = external_exports.union([ProductApiVersionSchema, ProductApiVersionV2Schema], {
|
|
13722
|
+
errorMap: () => ({ message: unsupportedProductApiVersionMessage() })
|
|
13723
|
+
}).describe("The Product contract format this document is written against.");
|
|
13069
13724
|
var ResourceApiVersionSchema = external_exports.literal(RESOURCE_API_VERSION, {
|
|
13070
13725
|
errorMap: () => ({
|
|
13071
13726
|
message: `apiVersion must be "${RESOURCE_API_VERSION}". An unrecognized contract format is refused rather than ignored.`
|
|
@@ -13442,6 +14097,18 @@ var ProductConditionSchema = external_exports.object({
|
|
|
13442
14097
|
*/
|
|
13443
14098
|
description: external_exports.string().min(10).max(300)
|
|
13444
14099
|
}).strict();
|
|
14100
|
+
var RequiredWhenSchema = external_exports.object({
|
|
14101
|
+
/** A declared, non-secret customer-configuration property. */
|
|
14102
|
+
property: external_exports.string().regex(CONFIGURATION_PROPERTY_NAME_REGEX, "Must name a declared customer-configuration property."),
|
|
14103
|
+
/** The values that make this dependency required. Non-empty. */
|
|
14104
|
+
anyOf: external_exports.array(external_exports.string().min(1).max(80)).min(1).max(40)
|
|
14105
|
+
}).strict();
|
|
14106
|
+
var RequiredWhenV2Schema = external_exports.object({
|
|
14107
|
+
path: external_exports.string().refine((raw) => parseConfigurationPath(raw) !== null, {
|
|
14108
|
+
message: 'A configuration path is a root property name, or an RFC 6901 pointer such as "/assistant/model".'
|
|
14109
|
+
}),
|
|
14110
|
+
anyOf: external_exports.array(external_exports.string().min(1).max(80)).min(1).max(40)
|
|
14111
|
+
}).strict();
|
|
13445
14112
|
var ProductDependencySchema = external_exports.object({
|
|
13446
14113
|
/**
|
|
13447
14114
|
* OPTIONAL ONLY WHEN `interface` IS PRESENT, enforced below.
|
|
@@ -13556,13 +14223,11 @@ var ProductDependencySchema = external_exports.object({
|
|
|
13556
14223
|
* `.optional()`, never `.default()` — see the Blueprint's banner on
|
|
13557
14224
|
* `runtime`. Every dependency published to date carries none.
|
|
13558
14225
|
*/
|
|
13559
|
-
requiredWhen:
|
|
13560
|
-
/** A declared, non-secret customer-configuration property. */
|
|
13561
|
-
property: external_exports.string().regex(CONFIGURATION_PROPERTY_NAME_REGEX, "Must name a declared customer-configuration property."),
|
|
13562
|
-
/** The values that make this dependency required. Non-empty. */
|
|
13563
|
-
anyOf: external_exports.array(external_exports.string().min(1).max(80)).min(1).max(40)
|
|
13564
|
-
}).strict().optional()
|
|
14226
|
+
requiredWhen: RequiredWhenSchema.optional()
|
|
13565
14227
|
}).strict();
|
|
14228
|
+
var ProductDependencyV2Schema = ProductDependencySchema.extend({
|
|
14229
|
+
requiredWhen: RequiredWhenV2Schema.optional()
|
|
14230
|
+
});
|
|
13566
14231
|
var ServiceInterfaceProvideSchema = external_exports.object({
|
|
13567
14232
|
key: ServiceBindingKeySchema,
|
|
13568
14233
|
interfaceId: ServiceInterfaceIdSchema,
|
|
@@ -13699,7 +14364,14 @@ var ProductDefinitionObjectSchema = external_exports.object({
|
|
|
13699
14364
|
*/
|
|
13700
14365
|
blueprint: external_exports.object({ version: ContractVersionSchema }).strict()
|
|
13701
14366
|
}).strict();
|
|
13702
|
-
var ProductDefinitionSchema = ProductDefinitionObjectSchema.superRefine(
|
|
14367
|
+
var ProductDefinitionSchema = ProductDefinitionObjectSchema.superRefine(checkProductDefinition);
|
|
14368
|
+
var ProductDefinitionV2ObjectSchema = ProductDefinitionObjectSchema.extend({
|
|
14369
|
+
apiVersion: ProductApiVersionV2Schema,
|
|
14370
|
+
configuration: CustomerConfigurationV2Schema,
|
|
14371
|
+
dependencies: external_exports.array(ProductDependencyV2Schema).max(8)
|
|
14372
|
+
});
|
|
14373
|
+
var ProductDefinitionV2Schema = ProductDefinitionV2ObjectSchema.superRefine(checkProductDefinition);
|
|
14374
|
+
function checkProductDefinition(definition, ctx) {
|
|
13703
14375
|
const profileIds = definition.profiles.map((profile) => profile.id);
|
|
13704
14376
|
const duplicateProfiles = profileIds.filter((id, i) => profileIds.indexOf(id) !== i);
|
|
13705
14377
|
if (duplicateProfiles.length > 0) {
|
|
@@ -13821,42 +14493,55 @@ var ProductDefinitionSchema = ProductDefinitionObjectSchema.superRefine((definit
|
|
|
13821
14493
|
message: "Repeated values in `anyOf`."
|
|
13822
14494
|
});
|
|
13823
14495
|
}
|
|
13824
|
-
const
|
|
13825
|
-
|
|
14496
|
+
const named = "path" in condition ? condition.path : condition.property;
|
|
14497
|
+
const member = "path" in condition ? "path" : "property";
|
|
14498
|
+
const parsed = parseConfigurationPath(named);
|
|
14499
|
+
const leaf = parsed === null ? null : leafAt(definition.configuration, parsed);
|
|
14500
|
+
if (leaf === null) {
|
|
14501
|
+
const isGroup = parsed !== null && declaresPath(definition.configuration, parsed);
|
|
14502
|
+
ctx.addIssue({
|
|
14503
|
+
code: external_exports.ZodIssueCode.custom,
|
|
14504
|
+
path: [...at, member],
|
|
14505
|
+
message: isGroup ? `"${named}" is a group of settings, which holds no single value to compare. Name one setting inside it.` : `"${named}" is not a declared customer configuration property.`
|
|
14506
|
+
});
|
|
14507
|
+
return;
|
|
14508
|
+
}
|
|
14509
|
+
if (leaf.container?.kind === "array") {
|
|
13826
14510
|
ctx.addIssue({
|
|
13827
14511
|
code: external_exports.ZodIssueCode.custom,
|
|
13828
|
-
path: [...at,
|
|
13829
|
-
message: `"${
|
|
14512
|
+
path: [...at, member],
|
|
14513
|
+
message: `"${named}" is inside a list, so it names one value per item rather than one value. A condition must name a setting the instance holds exactly once.`
|
|
13830
14514
|
});
|
|
13831
14515
|
return;
|
|
13832
14516
|
}
|
|
14517
|
+
const property = leaf.property;
|
|
13833
14518
|
if (property.type !== "string") {
|
|
13834
14519
|
ctx.addIssue({
|
|
13835
14520
|
code: external_exports.ZodIssueCode.custom,
|
|
13836
|
-
path: [...at,
|
|
13837
|
-
message: `"${
|
|
14521
|
+
path: [...at, member],
|
|
14522
|
+
message: `"${named}" is a ${property.type} setting; a condition compares string values.`
|
|
13838
14523
|
});
|
|
13839
14524
|
return;
|
|
13840
14525
|
}
|
|
13841
|
-
if (property
|
|
14526
|
+
if (isSecretProperty(property)) {
|
|
13842
14527
|
ctx.addIssue({
|
|
13843
14528
|
code: external_exports.ZodIssueCode.custom,
|
|
13844
|
-
path: [...at,
|
|
13845
|
-
message: `"${
|
|
14529
|
+
path: [...at, member],
|
|
14530
|
+
message: `"${named}" is a secret. The platform never reads a secret's value, so a condition on one could never be evaluated.`
|
|
13846
14531
|
});
|
|
13847
14532
|
return;
|
|
13848
14533
|
}
|
|
13849
14534
|
const single = withoutCrossFieldRules({
|
|
13850
14535
|
...definition.configuration,
|
|
13851
|
-
properties: { [
|
|
13852
|
-
required: [
|
|
14536
|
+
properties: { [leaf.name]: property },
|
|
14537
|
+
required: [leaf.name]
|
|
13853
14538
|
});
|
|
13854
|
-
const outside = condition.anyOf.filter((value) => !validateSubmittedConfiguration(single, { [
|
|
14539
|
+
const outside = condition.anyOf.filter((value) => !validateSubmittedConfiguration(single, { [leaf.name]: value }).ok);
|
|
13855
14540
|
if (outside.length > 0) {
|
|
13856
14541
|
ctx.addIssue({
|
|
13857
14542
|
code: external_exports.ZodIssueCode.custom,
|
|
13858
14543
|
path: [...at, "anyOf"],
|
|
13859
|
-
message: `"${
|
|
14544
|
+
message: `"${named}" never accepts ${outside.map((v) => `"${v}"`).join(", ")}, so this condition could never make the dependency required.`
|
|
13860
14545
|
});
|
|
13861
14546
|
}
|
|
13862
14547
|
});
|
|
@@ -13970,7 +14655,7 @@ var ProductDefinitionSchema = ProductDefinitionObjectSchema.superRefine((definit
|
|
|
13970
14655
|
message: 'dataResidency "global" contradicts externalProcessing false \u2014 data cannot be global without leaving the tenant boundary.'
|
|
13971
14656
|
});
|
|
13972
14657
|
}
|
|
13973
|
-
}
|
|
14658
|
+
}
|
|
13974
14659
|
|
|
13975
14660
|
// ../product-contracts/dist/announcements.js
|
|
13976
14661
|
var ANNOUNCED_PRODUCTS = Object.freeze([
|
|
@@ -14160,108 +14845,166 @@ var ComponentIngressSchema = external_exports.discriminatedUnion("exposure", [
|
|
|
14160
14845
|
authentication: external_exports.enum(["signed-request", "mtls"])
|
|
14161
14846
|
}).strict()
|
|
14162
14847
|
]);
|
|
14848
|
+
var LiteralEnvBindingSchema = external_exports.object({
|
|
14849
|
+
source: external_exports.literal("literal"),
|
|
14850
|
+
name: EnvVarNameSchema,
|
|
14851
|
+
value: external_exports.string().max(512)
|
|
14852
|
+
}).strict();
|
|
14853
|
+
var InstanceEnvBindingSchema = external_exports.object({
|
|
14854
|
+
source: external_exports.literal("instance"),
|
|
14855
|
+
name: EnvVarNameSchema,
|
|
14856
|
+
/** Closed set: the Control Plane knows these without Product knowledge. */
|
|
14857
|
+
field: external_exports.enum([
|
|
14858
|
+
"tenantKey",
|
|
14859
|
+
"tenantId",
|
|
14860
|
+
"projectId",
|
|
14861
|
+
"productInstanceId",
|
|
14862
|
+
"instanceKey",
|
|
14863
|
+
"productId",
|
|
14864
|
+
"productVersion",
|
|
14865
|
+
"profile",
|
|
14866
|
+
"region",
|
|
14867
|
+
"environment"
|
|
14868
|
+
])
|
|
14869
|
+
}).strict();
|
|
14870
|
+
var PlatformEnvBindingSchema = external_exports.object({
|
|
14871
|
+
source: external_exports.literal("platform"),
|
|
14872
|
+
name: EnvVarNameSchema,
|
|
14873
|
+
key: external_exports.enum(["controlPlaneUrl", "observabilityEndpoint", "logLevel", "serviceVersion"])
|
|
14874
|
+
}).strict();
|
|
14875
|
+
var ComponentEndpointEnvBindingSchema = external_exports.object({
|
|
14876
|
+
source: external_exports.literal("component-endpoint"),
|
|
14877
|
+
name: EnvVarNameSchema,
|
|
14878
|
+
/** Resolved to the sibling component's private URL at reconcile time. */
|
|
14879
|
+
componentId: ComponentIdSchema
|
|
14880
|
+
}).strict();
|
|
14881
|
+
var ComponentPublicUrlEnvBindingSchema = external_exports.object({
|
|
14882
|
+
/**
|
|
14883
|
+
* The CUSTOMER-FACING address of a PUBLIC component — the URL a browser
|
|
14884
|
+
* opens, not the in-network one a sibling calls.
|
|
14885
|
+
*
|
|
14886
|
+
* WHY THE PLATFORM HAS TO SUPPLY IT. The address is assigned during
|
|
14887
|
+
* deployment, so nobody knows it earlier: not the publisher, who writes
|
|
14888
|
+
* the contract months before, and not the customer, who would otherwise
|
|
14889
|
+
* be asked to type an address that does not exist yet. A console that
|
|
14890
|
+
* needs its own address — to build an OAuth redirect URI, to put an
|
|
14891
|
+
* absolute link in an email — had no way to learn it, and asking the
|
|
14892
|
+
* customer produced exactly the failure you would expect: an empty
|
|
14893
|
+
* setting and a console nobody can sign in to.
|
|
14894
|
+
*
|
|
14895
|
+
* It is deliberately NOT derivable from the request. A server behind a
|
|
14896
|
+
* proxy infers its bind address, which looks right in development and is
|
|
14897
|
+
* wrong in production; a forwarded Host header is attacker-controlled.
|
|
14898
|
+
* The platform knows the answer, so the platform states it.
|
|
14899
|
+
*
|
|
14900
|
+
* `componentId` may name this component or another, but it must be a
|
|
14901
|
+
* PUBLIC one: `validateProductContracts` refuses a private target, the
|
|
14902
|
+
* same rule `outputs` already carries, because a private endpoint is not
|
|
14903
|
+
* an address to hand out.
|
|
14904
|
+
*/
|
|
14905
|
+
source: external_exports.literal("component-public-url"),
|
|
14906
|
+
name: EnvVarNameSchema,
|
|
14907
|
+
componentId: ComponentIdSchema
|
|
14908
|
+
}).strict();
|
|
14909
|
+
var ServiceBindingAttributeEnvBindingSchema = external_exports.object({
|
|
14910
|
+
/**
|
|
14911
|
+
* A NON-SECRET value from a service binding to ANOTHER Product.
|
|
14912
|
+
*
|
|
14913
|
+
* THE ONLY SOURCE THAT LEAVES THIS PRODUCT INSTANCE. Every other member of
|
|
14914
|
+
* this union resolves inside one deployment: a literal, a fact about this
|
|
14915
|
+
* instance, a sibling component's address, a setting this customer typed.
|
|
14916
|
+
* This one is answered by a different Product Instance, possibly in a
|
|
14917
|
+
* different logical Project, which is why it is the only source whose
|
|
14918
|
+
* value can be absent for a reason that is nobody's mistake.
|
|
14919
|
+
*
|
|
14920
|
+
* ABSENT WHILE THE BINDING IS PENDING, and absent rather than empty. The
|
|
14921
|
+
* variable is left out of the container entirely until the provider
|
|
14922
|
+
* completes the binding, so a Product can tell "not yet" from "set to
|
|
14923
|
+
* nothing" — the same rule `configuration` already follows. Read
|
|
14924
|
+
* `VFAC_SERVICE_BINDING_<KEY>_STATUS`, which the platform injects for
|
|
14925
|
+
* every declared binding, rather than inferring readiness from absence.
|
|
14926
|
+
*
|
|
14927
|
+
* CREDENTIALS DO NOT COME THIS WAY. `field` must name a field the
|
|
14928
|
+
* interface classifies as an attribute; a secret field bound here is
|
|
14929
|
+
* refused by `validateProductContracts()`, and the credential-shaped-name
|
|
14930
|
+
* rule below refuses the variable name independently.
|
|
14931
|
+
*/
|
|
14932
|
+
source: external_exports.literal("service-binding-attribute"),
|
|
14933
|
+
name: EnvVarNameSchema,
|
|
14934
|
+
/** The `serviceBindings[].key` this value comes from. */
|
|
14935
|
+
binding: ServiceBindingKeySchema,
|
|
14936
|
+
/** The interface field, e.g. `issuerUrl`. Checked against the registry. */
|
|
14937
|
+
field: external_exports.string().regex(/^[a-z][a-zA-Z0-9]{1,47}$/)
|
|
14938
|
+
}).strict();
|
|
14939
|
+
var ConfigurationEnvBindingSchema = external_exports.object({
|
|
14940
|
+
source: external_exports.literal("configuration"),
|
|
14941
|
+
name: EnvVarNameSchema,
|
|
14942
|
+
/**
|
|
14943
|
+
* A NON-SECRET customer setting from the Product Definition.
|
|
14944
|
+
* `validateProductContracts()` rejects a reference to an `x-secret`
|
|
14945
|
+
* property — those travel through `secrets[]` and Secret Manager, never
|
|
14946
|
+
* through plain environment wiring.
|
|
14947
|
+
*/
|
|
14948
|
+
property: external_exports.string().regex(/^[a-z][a-zA-Z0-9]{1,47}$/)
|
|
14949
|
+
}).strict();
|
|
14163
14950
|
var EnvBindingSchema = external_exports.discriminatedUnion("source", [
|
|
14951
|
+
LiteralEnvBindingSchema,
|
|
14952
|
+
InstanceEnvBindingSchema,
|
|
14953
|
+
PlatformEnvBindingSchema,
|
|
14954
|
+
ComponentEndpointEnvBindingSchema,
|
|
14955
|
+
ComponentPublicUrlEnvBindingSchema,
|
|
14956
|
+
ServiceBindingAttributeEnvBindingSchema,
|
|
14957
|
+
ConfigurationEnvBindingSchema
|
|
14958
|
+
]);
|
|
14959
|
+
var ConfigurationBindingPathSchema = external_exports.string().refine((raw) => parseConfigurationPath(raw) !== null, {
|
|
14960
|
+
message: 'A configuration path is a root property name, or an RFC 6901 pointer such as "/assistant/model".'
|
|
14961
|
+
}).refine((raw) => !/\/\d+(\/|$)/.test(raw), {
|
|
14962
|
+
message: 'A Blueprint binds a DECLARED setting, so a path may not carry a list index. Bind the list with "configuration-json".'
|
|
14963
|
+
});
|
|
14964
|
+
var EnvBindingV2Schema = external_exports.discriminatedUnion("source", [
|
|
14965
|
+
LiteralEnvBindingSchema,
|
|
14966
|
+
InstanceEnvBindingSchema,
|
|
14967
|
+
PlatformEnvBindingSchema,
|
|
14968
|
+
ComponentEndpointEnvBindingSchema,
|
|
14969
|
+
ComponentPublicUrlEnvBindingSchema,
|
|
14970
|
+
ServiceBindingAttributeEnvBindingSchema,
|
|
14164
14971
|
external_exports.object({
|
|
14165
|
-
source: external_exports.literal("
|
|
14166
|
-
name: EnvVarNameSchema,
|
|
14167
|
-
value: external_exports.string().max(512)
|
|
14168
|
-
}).strict(),
|
|
14169
|
-
external_exports.object({
|
|
14170
|
-
source: external_exports.literal("instance"),
|
|
14171
|
-
name: EnvVarNameSchema,
|
|
14172
|
-
/** Closed set: the Control Plane knows these without Product knowledge. */
|
|
14173
|
-
field: external_exports.enum([
|
|
14174
|
-
"tenantKey",
|
|
14175
|
-
"tenantId",
|
|
14176
|
-
"projectId",
|
|
14177
|
-
"productInstanceId",
|
|
14178
|
-
"instanceKey",
|
|
14179
|
-
"productId",
|
|
14180
|
-
"productVersion",
|
|
14181
|
-
"profile",
|
|
14182
|
-
"region",
|
|
14183
|
-
"environment"
|
|
14184
|
-
])
|
|
14185
|
-
}).strict(),
|
|
14186
|
-
external_exports.object({
|
|
14187
|
-
source: external_exports.literal("platform"),
|
|
14188
|
-
name: EnvVarNameSchema,
|
|
14189
|
-
key: external_exports.enum(["controlPlaneUrl", "observabilityEndpoint", "logLevel", "serviceVersion"])
|
|
14190
|
-
}).strict(),
|
|
14191
|
-
external_exports.object({
|
|
14192
|
-
source: external_exports.literal("component-endpoint"),
|
|
14972
|
+
source: external_exports.literal("configuration"),
|
|
14193
14973
|
name: EnvVarNameSchema,
|
|
14194
|
-
/** Resolved to the sibling component's private URL at reconcile time. */
|
|
14195
|
-
componentId: ComponentIdSchema
|
|
14196
|
-
}).strict(),
|
|
14197
|
-
external_exports.object({
|
|
14198
14974
|
/**
|
|
14199
|
-
*
|
|
14200
|
-
* opens, not the in-network one a sibling calls.
|
|
14201
|
-
*
|
|
14202
|
-
* WHY THE PLATFORM HAS TO SUPPLY IT. The address is assigned during
|
|
14203
|
-
* deployment, so nobody knows it earlier: not the publisher, who writes
|
|
14204
|
-
* the contract months before, and not the customer, who would otherwise
|
|
14205
|
-
* be asked to type an address that does not exist yet. A console that
|
|
14206
|
-
* needs its own address — to build an OAuth redirect URI, to put an
|
|
14207
|
-
* absolute link in an email — had no way to learn it, and asking the
|
|
14208
|
-
* customer produced exactly the failure you would expect: an empty
|
|
14209
|
-
* setting and a console nobody can sign in to.
|
|
14210
|
-
*
|
|
14211
|
-
* It is deliberately NOT derivable from the request. A server behind a
|
|
14212
|
-
* proxy infers its bind address, which looks right in development and is
|
|
14213
|
-
* wrong in production; a forwarded Host header is attacker-controlled.
|
|
14214
|
-
* The platform knows the answer, so the platform states it.
|
|
14975
|
+
* A NON-SECRET customer setting, named by its canonical path.
|
|
14215
14976
|
*
|
|
14216
|
-
* `
|
|
14217
|
-
*
|
|
14218
|
-
*
|
|
14219
|
-
*
|
|
14977
|
+
* `validateProductContracts` refuses a path that names no leaf, a path
|
|
14978
|
+
* that names a GROUP — a group has no scalar rendering, and
|
|
14979
|
+
* `configuration-json` is how one is carried — and any `x-secret`
|
|
14980
|
+
* property, which travels through `secrets[]` and never through plain
|
|
14981
|
+
* environment wiring.
|
|
14220
14982
|
*/
|
|
14221
|
-
|
|
14222
|
-
name: EnvVarNameSchema,
|
|
14223
|
-
componentId: ComponentIdSchema
|
|
14983
|
+
path: ConfigurationBindingPathSchema
|
|
14224
14984
|
}).strict(),
|
|
14225
14985
|
external_exports.object({
|
|
14986
|
+
source: external_exports.literal("configuration-json"),
|
|
14987
|
+
name: EnvVarNameSchema,
|
|
14226
14988
|
/**
|
|
14227
|
-
*
|
|
14989
|
+
* THE WHOLE VALIDATED CONFIGURATION, OR ONE SUBTREE OF IT, AS JSON.
|
|
14228
14990
|
*
|
|
14229
|
-
*
|
|
14230
|
-
*
|
|
14231
|
-
*
|
|
14232
|
-
*
|
|
14233
|
-
*
|
|
14234
|
-
*
|
|
14991
|
+
* WHY THIS EXISTS. A component may carry at most forty environment
|
|
14992
|
+
* bindings, and a nested Product spends one per leaf — so the format that
|
|
14993
|
+
* lets a Product have structure would immediately run out of room to
|
|
14994
|
+
* deliver it. This binds a whole document instead, and the Product's own
|
|
14995
|
+
* runtime translates it into whatever shape it wants. The Control Plane
|
|
14996
|
+
* learns nothing about that shape, which is the point.
|
|
14235
14997
|
*
|
|
14236
|
-
*
|
|
14237
|
-
*
|
|
14238
|
-
*
|
|
14239
|
-
*
|
|
14240
|
-
*
|
|
14241
|
-
*
|
|
14998
|
+
* WHAT IT CARRIES: validated, non-secret configuration with resolved
|
|
14999
|
+
* ORDINARY resource references materialised in place. Never a secret
|
|
15000
|
+
* value — secrets are root-only and travel through `secrets[]`, and a
|
|
15001
|
+
* subtree cannot contain one. Serialised with `canonicalJson`, so the same
|
|
15002
|
+
* logical configuration is the same bytes and the environment fingerprint
|
|
15003
|
+
* does not move on key order alone.
|
|
14242
15004
|
*
|
|
14243
|
-
*
|
|
14244
|
-
* interface classifies as an attribute; a secret field bound here is
|
|
14245
|
-
* refused by `validateProductContracts()`, and the credential-shaped-name
|
|
14246
|
-
* rule below refuses the variable name independently.
|
|
14247
|
-
*/
|
|
14248
|
-
source: external_exports.literal("service-binding-attribute"),
|
|
14249
|
-
name: EnvVarNameSchema,
|
|
14250
|
-
/** The `serviceBindings[].key` this value comes from. */
|
|
14251
|
-
binding: ServiceBindingKeySchema,
|
|
14252
|
-
/** The interface field, e.g. `issuerUrl`. Checked against the registry. */
|
|
14253
|
-
field: external_exports.string().regex(/^[a-z][a-zA-Z0-9]{1,47}$/)
|
|
14254
|
-
}).strict(),
|
|
14255
|
-
external_exports.object({
|
|
14256
|
-
source: external_exports.literal("configuration"),
|
|
14257
|
-
name: EnvVarNameSchema,
|
|
14258
|
-
/**
|
|
14259
|
-
* A NON-SECRET customer setting from the Product Definition.
|
|
14260
|
-
* `validateProductContracts()` rejects a reference to an `x-secret`
|
|
14261
|
-
* property — those travel through `secrets[]` and Secret Manager, never
|
|
14262
|
-
* through plain environment wiring.
|
|
15005
|
+
* Absent `path` means the whole document.
|
|
14263
15006
|
*/
|
|
14264
|
-
|
|
15007
|
+
path: ConfigurationBindingPathSchema.optional()
|
|
14265
15008
|
}).strict()
|
|
14266
15009
|
]);
|
|
14267
15010
|
var MAX_BOOTSTRAP_SCRIPT_LENGTH = 32768;
|
|
@@ -14473,11 +15216,12 @@ var ComponentDependencySchema = external_exports.object({
|
|
|
14473
15216
|
minVersion: ContractVersionSchema.optional(),
|
|
14474
15217
|
maxVersion: ContractVersionSchema.optional()
|
|
14475
15218
|
}).strict();
|
|
15219
|
+
var MAX_COMPONENT_ENV_BINDINGS = 40;
|
|
14476
15220
|
var componentCommonShape = {
|
|
14477
15221
|
id: ComponentIdSchema.describe("Scoped by its Product; does not repeat the Product ID (\xA78)."),
|
|
14478
15222
|
kind: ComponentKindSchema,
|
|
14479
15223
|
description: external_exports.string().min(10).max(300),
|
|
14480
|
-
env: external_exports.array(EnvBindingSchema).max(
|
|
15224
|
+
env: external_exports.array(EnvBindingSchema).max(MAX_COMPONENT_ENV_BINDINGS),
|
|
14481
15225
|
dependsOn: external_exports.array(ComponentDependencySchema).max(8)
|
|
14482
15226
|
};
|
|
14483
15227
|
var ServerlessContainerComponentSchema = external_exports.object({
|
|
@@ -14529,6 +15273,16 @@ var RuntimeComponentSchema = external_exports.discriminatedUnion("runtime", [
|
|
|
14529
15273
|
ServerlessContainerComponentSchema,
|
|
14530
15274
|
VirtualMachineComponentSchema
|
|
14531
15275
|
]);
|
|
15276
|
+
var ServerlessContainerComponentV2Schema = ServerlessContainerComponentSchema.extend({
|
|
15277
|
+
env: external_exports.array(EnvBindingV2Schema).max(MAX_COMPONENT_ENV_BINDINGS)
|
|
15278
|
+
});
|
|
15279
|
+
var VirtualMachineComponentV2Schema = VirtualMachineComponentSchema.extend({
|
|
15280
|
+
env: external_exports.array(EnvBindingV2Schema).max(MAX_COMPONENT_ENV_BINDINGS)
|
|
15281
|
+
});
|
|
15282
|
+
var RuntimeComponentV2Schema = external_exports.discriminatedUnion("runtime", [
|
|
15283
|
+
ServerlessContainerComponentV2Schema,
|
|
15284
|
+
VirtualMachineComponentV2Schema
|
|
15285
|
+
]);
|
|
14532
15286
|
function isVirtualMachineComponent(component) {
|
|
14533
15287
|
return component.runtime === "virtual-machine";
|
|
14534
15288
|
}
|
|
@@ -14777,7 +15531,47 @@ var BlueprintLifecycleSchema = external_exports.object({
|
|
|
14777
15531
|
* the service-interface surface is unchanged. Nothing published to date
|
|
14778
15532
|
* regresses, and a release cannot strand an instance by forgetting it.
|
|
14779
15533
|
*/
|
|
14780
|
-
directFromVersions: external_exports.array(ContractVersionSchema).max(20).optional()
|
|
15534
|
+
directFromVersions: external_exports.array(ContractVersionSchema).max(20).optional(),
|
|
15535
|
+
/**
|
|
15536
|
+
* How a stored configuration is carried across a release that MOVED a
|
|
15537
|
+
* setting.
|
|
15538
|
+
*
|
|
15539
|
+
* THE CASE THIS EXISTS FOR is a flat Product taking on structure:
|
|
15540
|
+
* `assistantName` becomes `/assistant/name`. Nothing else on this
|
|
15541
|
+
* platform can express that. Without it the target release simply does
|
|
15542
|
+
* not declare `assistantName`, so the upgrade drops the customer's value
|
|
15543
|
+
* and then refuses the deploy for a missing required setting — and the
|
|
15544
|
+
* customer's answer is gone either way.
|
|
15545
|
+
*
|
|
15546
|
+
* `move` AND NOTHING ELSE. A migration the platform cannot fully
|
|
15547
|
+
* evaluate is one it cannot apply safely, and every other operation a
|
|
15548
|
+
* publisher might want — rename a value, split one setting into two,
|
|
15549
|
+
* compute a default — needs the Product's own knowledge of what those
|
|
15550
|
+
* values MEAN. Moving a value is the one thing the platform can do
|
|
15551
|
+
* correctly without knowing anything about it.
|
|
15552
|
+
*
|
|
15553
|
+
* APPLIED AT CUTOVER, in the transaction that writes the new
|
|
15554
|
+
* configuration, and to the REFERENCE ROWS as well as the stored
|
|
15555
|
+
* document — a Resource Reference is identified by the path it answers,
|
|
15556
|
+
* so a setting that moved takes its edge with it or the edge points at
|
|
15557
|
+
* nothing.
|
|
15558
|
+
*
|
|
15559
|
+
* AN ABSENT SOURCE IS A NO-OP, deliberately. A customer who never
|
|
15560
|
+
* answered an optional setting has nothing to carry, and inventing an
|
|
15561
|
+
* empty value for them would turn "not configured" into "configured
|
|
15562
|
+
* blank" — two states this platform keeps apart everywhere else.
|
|
15563
|
+
*
|
|
15564
|
+
* `.optional()`, never `.default([])`, for the reason
|
|
15565
|
+
* `directFromVersions` states one field above: a materialised key makes
|
|
15566
|
+
* a byte-identical republish `RELEASED_CONTRACT_MUTATED`.
|
|
15567
|
+
*/
|
|
15568
|
+
configurationMigrations: external_exports.array(external_exports.object({
|
|
15569
|
+
op: external_exports.literal("move"),
|
|
15570
|
+
/** Where the value is today, in the release being left. */
|
|
15571
|
+
from: ConfigurationBindingPathSchema,
|
|
15572
|
+
/** Where this release declares it. */
|
|
15573
|
+
to: ConfigurationBindingPathSchema
|
|
15574
|
+
}).strict()).max(40).optional()
|
|
14781
15575
|
}).strict(),
|
|
14782
15576
|
rollback: external_exports.object({
|
|
14783
15577
|
supported: external_exports.boolean(),
|
|
@@ -14903,7 +15697,14 @@ function isOidcClientServiceBinding(binding) {
|
|
|
14903
15697
|
}
|
|
14904
15698
|
var DeploymentBlueprintObjectSchema = external_exports.object({
|
|
14905
15699
|
/** The CONTRACT FORMAT version — not the Blueprint's. See api-version.ts. */
|
|
14906
|
-
|
|
15700
|
+
/**
|
|
15701
|
+
* The SHARED base carries either literal; each format pins its own below.
|
|
15702
|
+
*
|
|
15703
|
+
* Nothing parses this object schema directly — `DeploymentBlueprintV1Schema`
|
|
15704
|
+
* and `…V2Schema` extend it — so the permissive literal here is never what a
|
|
15705
|
+
* document is held to, and never what an artifact publishes.
|
|
15706
|
+
*/
|
|
15707
|
+
apiVersion: ProductApiVersionAnySchema,
|
|
14907
15708
|
kind: kindSchema(DEPLOYMENT_BLUEPRINT_KIND),
|
|
14908
15709
|
productId: ProductIdSchema,
|
|
14909
15710
|
/** This Blueprint's own version. The Definition pins it exactly. */
|
|
@@ -14971,7 +15772,17 @@ var DeploymentBlueprintObjectSchema = external_exports.object({
|
|
|
14971
15772
|
outputs: external_exports.array(BlueprintOutputSchema).min(1).max(12),
|
|
14972
15773
|
lifecycle: BlueprintLifecycleSchema
|
|
14973
15774
|
}).strict();
|
|
14974
|
-
var
|
|
15775
|
+
var DeploymentBlueprintV1ObjectSchema = DeploymentBlueprintObjectSchema.extend({
|
|
15776
|
+
apiVersion: ProductApiVersionSchema
|
|
15777
|
+
});
|
|
15778
|
+
var DeploymentBlueprintV2ObjectSchema = DeploymentBlueprintObjectSchema.extend({
|
|
15779
|
+
apiVersion: ProductApiVersionV2Schema,
|
|
15780
|
+
components: external_exports.array(RuntimeComponentV2Schema).min(1).max(MAX_RUNTIME_COMPONENTS)
|
|
15781
|
+
});
|
|
15782
|
+
var DeploymentBlueprintV1Schema = DeploymentBlueprintV1ObjectSchema.superRefine(checkDeploymentBlueprint);
|
|
15783
|
+
var DeploymentBlueprintV2Schema = DeploymentBlueprintV2ObjectSchema.superRefine(checkDeploymentBlueprint);
|
|
15784
|
+
var DeploymentBlueprintSchema = DeploymentBlueprintV1Schema;
|
|
15785
|
+
function checkDeploymentBlueprint(blueprint, ctx) {
|
|
14975
15786
|
const componentIds = blueprint.components.map((component) => component.id);
|
|
14976
15787
|
const knownComponents = new Set(componentIds);
|
|
14977
15788
|
const publicComponents = new Set(blueprint.components.filter((component) => component.ingress.exposure === "public").map((component) => component.id));
|
|
@@ -15072,13 +15883,7 @@ var DeploymentBlueprintSchema = DeploymentBlueprintObjectSchema.superRefine((blu
|
|
|
15072
15883
|
});
|
|
15073
15884
|
const handoff = resource.bootstrap.productHandoff;
|
|
15074
15885
|
if (handoff !== void 0) {
|
|
15075
|
-
const handoffPath = [
|
|
15076
|
-
"dynamicResources",
|
|
15077
|
-
index,
|
|
15078
|
-
"bootstrap",
|
|
15079
|
-
"productHandoff",
|
|
15080
|
-
"componentId"
|
|
15081
|
-
];
|
|
15886
|
+
const handoffPath = ["dynamicResources", index, "bootstrap", "productHandoff", "componentId"];
|
|
15082
15887
|
const target = blueprint.components.find((component) => component.id === handoff.componentId);
|
|
15083
15888
|
if (target === void 0) {
|
|
15084
15889
|
ctx.addIssue({
|
|
@@ -15689,7 +16494,7 @@ var DeploymentBlueprintSchema = DeploymentBlueprintObjectSchema.superRefine((blu
|
|
|
15689
16494
|
});
|
|
15690
16495
|
}
|
|
15691
16496
|
}
|
|
15692
|
-
}
|
|
16497
|
+
}
|
|
15693
16498
|
|
|
15694
16499
|
// ../product-contracts/dist/deployability.js
|
|
15695
16500
|
var VIRTUAL_MACHINE_PROFILE_INTERFACE = {
|
|
@@ -15896,7 +16701,33 @@ var ProductSubmissionObjectSchema = external_exports.object({
|
|
|
15896
16701
|
definition: ProductDefinitionSchema,
|
|
15897
16702
|
blueprint: DeploymentBlueprintSchema
|
|
15898
16703
|
}).strict();
|
|
15899
|
-
var
|
|
16704
|
+
var submissionShape = {
|
|
16705
|
+
kind: kindSchema(PRODUCT_SUBMISSION_KIND),
|
|
16706
|
+
submission: SubmissionEnvelopeSchema
|
|
16707
|
+
};
|
|
16708
|
+
var ProductSubmissionV1ObjectSchema = external_exports.object({
|
|
16709
|
+
apiVersion: ProductApiVersionSchema,
|
|
16710
|
+
...submissionShape,
|
|
16711
|
+
definition: ProductDefinitionSchema,
|
|
16712
|
+
blueprint: DeploymentBlueprintV1Schema
|
|
16713
|
+
}).strict();
|
|
16714
|
+
var ProductSubmissionV2ObjectSchema = external_exports.object({
|
|
16715
|
+
apiVersion: ProductApiVersionV2Schema,
|
|
16716
|
+
...submissionShape,
|
|
16717
|
+
definition: ProductDefinitionV2Schema,
|
|
16718
|
+
blueprint: DeploymentBlueprintV2Schema
|
|
16719
|
+
}).strict();
|
|
16720
|
+
var ProductSubmissionV1Schema = ProductSubmissionV1ObjectSchema.superRefine(checkProductSubmission);
|
|
16721
|
+
var ProductSubmissionV2Schema = ProductSubmissionV2ObjectSchema.superRefine(checkProductSubmission);
|
|
16722
|
+
var ProductSubmissionSchema = ProductSubmissionV1Schema;
|
|
16723
|
+
function checkProductSubmission(submission, ctx) {
|
|
16724
|
+
if (submission.definition.apiVersion !== submission.apiVersion) {
|
|
16725
|
+
ctx.addIssue({
|
|
16726
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16727
|
+
path: ["definition", "apiVersion"],
|
|
16728
|
+
message: `This submission is written against "${submission.apiVersion}" but its Product Definition declares "${submission.definition.apiVersion}". One submission is one contract format.`
|
|
16729
|
+
});
|
|
16730
|
+
}
|
|
15900
16731
|
if (submission.definition.id !== submission.submission.productId) {
|
|
15901
16732
|
ctx.addIssue({
|
|
15902
16733
|
code: external_exports.ZodIssueCode.custom,
|
|
@@ -15918,7 +16749,7 @@ var ProductSubmissionSchema = ProductSubmissionObjectSchema.superRefine((submiss
|
|
|
15918
16749
|
message: `The Product Definition is version "${submission.definition.version}" but the submission claims "${submission.submission.version}". They must be the same version.`
|
|
15919
16750
|
});
|
|
15920
16751
|
}
|
|
15921
|
-
}
|
|
16752
|
+
}
|
|
15922
16753
|
var PUBLISH_RULE_ANNEX = {
|
|
15923
16754
|
allOf: [
|
|
15924
16755
|
{
|
|
@@ -16371,12 +17202,12 @@ async function runDoctor(parsed) {
|
|
|
16371
17202
|
ok: false,
|
|
16372
17203
|
detail: "not set. Run `vfac context set --endpoint https://your-organization.cloud.vardeflyt.no`, or set VFAC_ENDPOINT."
|
|
16373
17204
|
});
|
|
16374
|
-
return
|
|
17205
|
+
return report2(checks, json);
|
|
16375
17206
|
}
|
|
16376
17207
|
const checked = validateEndpoint(resolved.value, resolved.source);
|
|
16377
17208
|
if (!checked.ok) {
|
|
16378
17209
|
checks.push({ name: "Endpoint", ok: false, detail: checked.message });
|
|
16379
|
-
return
|
|
17210
|
+
return report2(checks, json);
|
|
16380
17211
|
}
|
|
16381
17212
|
const endpoint = checked.endpoint;
|
|
16382
17213
|
checks.push({
|
|
@@ -16396,16 +17227,16 @@ async function runDoctor(parsed) {
|
|
|
16396
17227
|
const probe = await probeMachineApi({ endpoint });
|
|
16397
17228
|
if (!probe.ok) {
|
|
16398
17229
|
checks.push({ name: "Machine API", ok: false, detail: probe.message });
|
|
16399
|
-
return
|
|
17230
|
+
return report2(checks, json);
|
|
16400
17231
|
}
|
|
16401
17232
|
checks.push({ name: "Machine API", ok: true, detail: probe.apiVersion });
|
|
16402
17233
|
const compatible = compatibility(cliVersion(), probe.minimumCliVersion);
|
|
16403
17234
|
checks.push(compatible);
|
|
16404
|
-
if (!compatible.ok) return
|
|
17235
|
+
if (!compatible.ok) return report2(checks, json);
|
|
16405
17236
|
const signedIn = await signIn({ endpoint });
|
|
16406
17237
|
if (!signedIn.ok) {
|
|
16407
17238
|
checks.push({ name: "Context Gate", ok: false, detail: signedIn.message });
|
|
16408
|
-
return
|
|
17239
|
+
return report2(checks, json);
|
|
16409
17240
|
}
|
|
16410
17241
|
checks.push({
|
|
16411
17242
|
name: "Context Gate",
|
|
@@ -16426,7 +17257,7 @@ async function runDoctor(parsed) {
|
|
|
16426
17257
|
ok: false,
|
|
16427
17258
|
detail: who.error.status === 404 ? "this Tenant Portal does not serve /api/v1/whoami yet \u2014 it is running an older build." : who.error.message
|
|
16428
17259
|
});
|
|
16429
|
-
return
|
|
17260
|
+
return report2(checks, json);
|
|
16430
17261
|
}
|
|
16431
17262
|
const access = who.data.access;
|
|
16432
17263
|
const projects = access.projects.map((project) => project.projectId);
|
|
@@ -16486,7 +17317,7 @@ async function runDoctor(parsed) {
|
|
|
16486
17317
|
detail: "run `vfac guide` for the platform's own instructions, written for a machine"
|
|
16487
17318
|
});
|
|
16488
17319
|
checks.push(await updateAvailable(cliVersion()));
|
|
16489
|
-
return
|
|
17320
|
+
return report2(checks, json);
|
|
16490
17321
|
}
|
|
16491
17322
|
function compatibility(local, declared) {
|
|
16492
17323
|
const name = "Compatibility";
|
|
@@ -16566,7 +17397,7 @@ async function updateAvailable(local) {
|
|
|
16566
17397
|
facts
|
|
16567
17398
|
};
|
|
16568
17399
|
}
|
|
16569
|
-
function
|
|
17400
|
+
function report2(checks, json) {
|
|
16570
17401
|
const failed = checks.filter((check) => !check.ok);
|
|
16571
17402
|
if (json) {
|
|
16572
17403
|
process.stdout.write(`${JSON.stringify({ ok: failed.length === 0, checks })}
|
|
@@ -16942,16 +17773,14 @@ function renderProduct(product) {
|
|
|
16942
17773
|
(profile) => `${profile.id}${profile.default ? " (default)" : ""}`
|
|
16943
17774
|
);
|
|
16944
17775
|
lines.push(` profile ${profiles.join(", ") || "(none declared)"}`);
|
|
16945
|
-
const
|
|
16946
|
-
|
|
16947
|
-
if (required.length > 0) {
|
|
17776
|
+
const seed = seedConfiguration(product.configuration);
|
|
17777
|
+
if (seed.open.length > 0 || seed.requiredSecrets.length > 0) {
|
|
16948
17778
|
lines.push("", " Required configuration");
|
|
16949
|
-
for (const name of
|
|
16950
|
-
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
);
|
|
17779
|
+
for (const name of seed.requiredSecrets) {
|
|
17780
|
+
lines.push(` ${name} (secret \u2014 pass --secret ${name}=env:VAR)`);
|
|
17781
|
+
}
|
|
17782
|
+
for (const setting of seed.open) {
|
|
17783
|
+
lines.push(` ${setting.label} ${setting.type ?? ""}`.trimEnd());
|
|
16955
17784
|
}
|
|
16956
17785
|
}
|
|
16957
17786
|
const needed = (product.dependencies ?? []).filter((dependency) => dependency.required);
|
|
@@ -17224,7 +18053,7 @@ async function runManifestInit(parsed) {
|
|
|
17224
18053
|
}
|
|
17225
18054
|
for (const setting of seed.open) {
|
|
17226
18055
|
notes.push(
|
|
17227
|
-
`spec.configuration.${setting.
|
|
18056
|
+
`spec.configuration.${setting.label} \u2014 required${setting.type ? ` (${setting.type})` : ""}`
|
|
17228
18057
|
);
|
|
17229
18058
|
}
|
|
17230
18059
|
for (const group of seed.groups) {
|