@varde-flyt/vfac 0.7.1 → 0.9.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 +1329 -423
- package/package.json +1 -1
package/dist/vfac.mjs
CHANGED
|
@@ -11988,12 +11988,26 @@ var coerce = {
|
|
|
11988
11988
|
};
|
|
11989
11989
|
var NEVER = INVALID;
|
|
11990
11990
|
|
|
11991
|
+
// ../product-configuration/dist/configuration-bounds.js
|
|
11992
|
+
var MAX_CONFIGURATION_DEPTH = 6;
|
|
11993
|
+
var MAX_CONFIGURATION_LEAVES = 256;
|
|
11994
|
+
var MAX_CONFIGURATION_NODES = 512;
|
|
11995
|
+
var MAX_CONFIGURATION_CHILDREN = 64;
|
|
11996
|
+
var MAX_CONFIGURATION_VALUE_LEAVES = 1e3;
|
|
11997
|
+
var MAX_CONFIGURATION_ISSUES = 50;
|
|
11998
|
+
var MAX_CONFIGURATION_VALUE_BYTES = 16384;
|
|
11999
|
+
|
|
11991
12000
|
// ../product-configuration/dist/json-schema-annex.js
|
|
11992
12001
|
var ANNEXES = /* @__PURE__ */ new WeakMap();
|
|
11993
12002
|
function withJsonSchemaAnnex(schema, annex) {
|
|
11994
12003
|
ANNEXES.set(schema, annex);
|
|
11995
12004
|
return schema;
|
|
11996
12005
|
}
|
|
12006
|
+
var DEFINITION_NAMES = /* @__PURE__ */ new WeakMap();
|
|
12007
|
+
function withJsonSchemaDefinition(schema, name) {
|
|
12008
|
+
DEFINITION_NAMES.set(schema, name);
|
|
12009
|
+
return schema;
|
|
12010
|
+
}
|
|
11997
12011
|
|
|
11998
12012
|
// ../product-configuration/dist/infrastructure-vocabulary.js
|
|
11999
12013
|
function tokenizeIdentifier(identifier) {
|
|
@@ -12211,7 +12225,20 @@ var ConfigurationGroupSchema = external_exports.enum([
|
|
|
12211
12225
|
var CONFIGURATION_PROPERTY_NAME_REGEX = /^[a-z][a-zA-Z0-9]{1,47}$/;
|
|
12212
12226
|
var PropertyNameSchema = external_exports.string().regex(CONFIGURATION_PROPERTY_NAME_REGEX, "Configuration property names must be camelCase, start with a lowercase letter, and be 2\u201348 characters.");
|
|
12213
12227
|
var TitleSchema = external_exports.string().min(2).max(80).describe("Customer-facing field label.");
|
|
12214
|
-
var
|
|
12228
|
+
var V1_LEAF_BOUNDS = {
|
|
12229
|
+
help: 400,
|
|
12230
|
+
enumValues: 40,
|
|
12231
|
+
stringLength: 4096,
|
|
12232
|
+
defaultLength: 400
|
|
12233
|
+
};
|
|
12234
|
+
var V2_LEAF_BOUNDS = {
|
|
12235
|
+
help: 2e3,
|
|
12236
|
+
enumValues: 256,
|
|
12237
|
+
stringLength: 16384,
|
|
12238
|
+
defaultLength: 2e3
|
|
12239
|
+
};
|
|
12240
|
+
var MAX_DECLARABLE_STRING_LENGTH = V2_LEAF_BOUNDS.stringLength;
|
|
12241
|
+
var helpTextSchema = (bounds) => external_exports.string().min(10).max(bounds.help).describe("Customer-facing explanation. Required for security-sensitive choices.");
|
|
12215
12242
|
var SECRET_COUPLING_ANNEX = {
|
|
12216
12243
|
allOf: [
|
|
12217
12244
|
{
|
|
@@ -12230,69 +12257,156 @@ var SECRET_COUPLING_ANNEX = {
|
|
|
12230
12257
|
}
|
|
12231
12258
|
]
|
|
12232
12259
|
};
|
|
12233
|
-
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
|
|
12241
|
-
|
|
12242
|
-
|
|
12243
|
-
|
|
12244
|
-
|
|
12245
|
-
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
|
|
12249
|
-
|
|
12250
|
-
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12255
|
-
|
|
12256
|
-
|
|
12257
|
-
|
|
12258
|
-
|
|
12259
|
-
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
12264
|
-
|
|
12265
|
-
|
|
12266
|
-
|
|
12267
|
-
|
|
12268
|
-
|
|
12269
|
-
|
|
12270
|
-
|
|
12271
|
-
|
|
12272
|
-
|
|
12273
|
-
|
|
12274
|
-
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
|
|
12278
|
-
|
|
12279
|
-
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
|
|
12285
|
-
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12260
|
+
function leafShapes(bounds) {
|
|
12261
|
+
const help = helpTextSchema(bounds);
|
|
12262
|
+
const enumMembers = external_exports.array(external_exports.string().min(1).max(80)).min(1).max(bounds.enumValues).optional();
|
|
12263
|
+
const string = external_exports.object({
|
|
12264
|
+
type: external_exports.literal("string"),
|
|
12265
|
+
title: TitleSchema,
|
|
12266
|
+
description: help.optional(),
|
|
12267
|
+
group: ConfigurationGroupSchema,
|
|
12268
|
+
enum: enumMembers,
|
|
12269
|
+
minLength: external_exports.number().int().min(0).max(bounds.stringLength).optional(),
|
|
12270
|
+
/**
|
|
12271
|
+
* Required unless the value is constrained by `enum`. An unbounded string
|
|
12272
|
+
* reaching the Control Plane as desired state is an unbounded write.
|
|
12273
|
+
*/
|
|
12274
|
+
maxLength: external_exports.number().int().min(1).max(bounds.stringLength).optional(),
|
|
12275
|
+
pattern: external_exports.string().min(1).max(200).optional(),
|
|
12276
|
+
default: external_exports.string().max(bounds.defaultLength).optional(),
|
|
12277
|
+
/**
|
|
12278
|
+
* docs/PRODUCT_DEFINITION_GUIDE.md "Secrets": secret input is marked
|
|
12279
|
+
* write-only AND secret. Both flags, and the refinement below makes one
|
|
12280
|
+
* without the other a validation error.
|
|
12281
|
+
*/
|
|
12282
|
+
writeOnly: external_exports.boolean().optional(),
|
|
12283
|
+
"x-secret": external_exports.boolean().optional()
|
|
12284
|
+
}).strict();
|
|
12285
|
+
withJsonSchemaAnnex(string, SECRET_COUPLING_ANNEX);
|
|
12286
|
+
const number = external_exports.object({
|
|
12287
|
+
type: external_exports.enum(["integer", "number"]),
|
|
12288
|
+
title: TitleSchema,
|
|
12289
|
+
description: help.optional(),
|
|
12290
|
+
group: ConfigurationGroupSchema,
|
|
12291
|
+
/** Both bounds required — "numeric limits" in the guide is not optional. */
|
|
12292
|
+
minimum: external_exports.number(),
|
|
12293
|
+
maximum: external_exports.number(),
|
|
12294
|
+
default: external_exports.number().optional()
|
|
12295
|
+
}).strict();
|
|
12296
|
+
const boolean = external_exports.object({
|
|
12297
|
+
type: external_exports.literal("boolean"),
|
|
12298
|
+
title: TitleSchema,
|
|
12299
|
+
description: help.optional(),
|
|
12300
|
+
group: ConfigurationGroupSchema,
|
|
12301
|
+
default: external_exports.boolean().optional()
|
|
12302
|
+
}).strict();
|
|
12303
|
+
const items = external_exports.object({
|
|
12304
|
+
type: external_exports.literal("string"),
|
|
12305
|
+
enum: enumMembers,
|
|
12306
|
+
maxLength: external_exports.number().int().min(1).max(bounds.defaultLength).optional()
|
|
12307
|
+
}).strict();
|
|
12308
|
+
const array = external_exports.object({
|
|
12309
|
+
type: external_exports.literal("array"),
|
|
12310
|
+
title: TitleSchema,
|
|
12311
|
+
description: help.optional(),
|
|
12312
|
+
group: ConfigurationGroupSchema,
|
|
12313
|
+
items,
|
|
12314
|
+
minItems: external_exports.number().int().min(0).max(100).optional(),
|
|
12315
|
+
/** Required: an unbounded list is an unbounded write. */
|
|
12316
|
+
maxItems: external_exports.number().int().min(1).max(100),
|
|
12317
|
+
uniqueItems: external_exports.boolean().optional(),
|
|
12318
|
+
default: external_exports.array(external_exports.string().max(200)).max(100).optional()
|
|
12319
|
+
}).strict();
|
|
12320
|
+
return { string, number, boolean, items, array };
|
|
12321
|
+
}
|
|
12322
|
+
var V1_LEAVES = leafShapes(V1_LEAF_BOUNDS);
|
|
12323
|
+
var V2_LEAVES = leafShapes(V2_LEAF_BOUNDS);
|
|
12324
|
+
var StringPropertySchema = V1_LEAVES.string;
|
|
12325
|
+
var NumberPropertySchema = V1_LEAVES.number;
|
|
12326
|
+
var BooleanPropertySchema = V1_LEAVES.boolean;
|
|
12327
|
+
var ArrayPropertySchema = V1_LEAVES.array;
|
|
12328
|
+
var MAX_CONFIGURATION_PROPERTIES = 40;
|
|
12290
12329
|
var ConfigurationPropertySchema = external_exports.discriminatedUnion("type", [
|
|
12291
12330
|
StringPropertySchema,
|
|
12292
12331
|
NumberPropertySchema,
|
|
12293
12332
|
BooleanPropertySchema,
|
|
12294
12333
|
ArrayPropertySchema
|
|
12295
12334
|
]);
|
|
12335
|
+
var NestedStringPropertySchema = V2_LEAVES.string.omit({ "x-secret": true, writeOnly: true }).extend({ group: ConfigurationGroupSchema.optional() });
|
|
12336
|
+
var V2_NESTED_LEAVES = {
|
|
12337
|
+
string: NestedStringPropertySchema,
|
|
12338
|
+
number: V2_LEAVES.number.extend({ group: ConfigurationGroupSchema.optional() }),
|
|
12339
|
+
boolean: V2_LEAVES.boolean.extend({ group: ConfigurationGroupSchema.optional() }),
|
|
12340
|
+
array: V2_LEAVES.array.extend({ group: ConfigurationGroupSchema.optional() }),
|
|
12341
|
+
items: V2_LEAVES.items
|
|
12342
|
+
};
|
|
12343
|
+
function childBagShape(child) {
|
|
12344
|
+
return {
|
|
12345
|
+
properties: external_exports.record(PropertyNameSchema, child),
|
|
12346
|
+
required: external_exports.array(PropertyNameSchema).max(MAX_CONFIGURATION_CHILDREN).optional(),
|
|
12347
|
+
/**
|
|
12348
|
+
* All-or-none rules, scoped to THIS container.
|
|
12349
|
+
*
|
|
12350
|
+
* ON THE CONTAINER, NEVER AS ROOT CLAUSES NAMING PATHS. The published key
|
|
12351
|
+
* promises that "a publisher running an off-the-shelf validator over that
|
|
12352
|
+
* file must get the answer the platform gives", and JSON Schema 2020-12
|
|
12353
|
+
* scopes `dependentRequired` to the object that CARRIES it. A root clause
|
|
12354
|
+
* naming `/upstream/token` would be a rule no standard validator applies —
|
|
12355
|
+
* the one thing this key may not become. Written here it keeps exactly the
|
|
12356
|
+
* meaning it has everywhere else, and the generated artifact carries it on
|
|
12357
|
+
* the right node.
|
|
12358
|
+
*
|
|
12359
|
+
* A REPEATABLE GROUP GETS ONE PER ROW, which is the honest reading: "if this
|
|
12360
|
+
* server has a URL it needs a token" is a fact about a server, not about the
|
|
12361
|
+
* list.
|
|
12362
|
+
*/
|
|
12363
|
+
dependentRequired: external_exports.record(PropertyNameSchema, external_exports.array(PropertyNameSchema).min(1).max(MAX_CONFIGURATION_CHILDREN)).optional().describe("Settings inside this group that must be supplied together."),
|
|
12364
|
+
additionalProperties: external_exports.literal(false)
|
|
12365
|
+
};
|
|
12366
|
+
}
|
|
12367
|
+
function propertyUnion(levelsBelow, leafSet) {
|
|
12368
|
+
const leaves = [leafSet.string, leafSet.number, leafSet.boolean];
|
|
12369
|
+
if (levelsBelow <= 0) {
|
|
12370
|
+
return [...leaves, leafSet.array];
|
|
12371
|
+
}
|
|
12372
|
+
const level = MAX_CONFIGURATION_DEPTH - levelsBelow + 1;
|
|
12373
|
+
const child = withJsonSchemaDefinition(external_exports.discriminatedUnion("type", propertyUnion(levelsBelow - 1, V2_NESTED_LEAVES)), `configurationPropertyLevel${level}`);
|
|
12374
|
+
const bag = childBagShape(child);
|
|
12375
|
+
const groupItems = external_exports.object({ type: external_exports.literal("object"), ...bag }).strict();
|
|
12376
|
+
return [
|
|
12377
|
+
...leaves,
|
|
12378
|
+
// ONE `array` BRANCH, NOT TWO, because a discriminated union may not carry
|
|
12379
|
+
// two options with the same discriminator value ("duplicate value array" —
|
|
12380
|
+
// zod refuses it at construction). The item shape is the inner
|
|
12381
|
+
// discriminator, which is also what keeps a v1 document's
|
|
12382
|
+
// `items: {type: 'string'}` reading exactly as it always did.
|
|
12383
|
+
leafSet.array.extend({
|
|
12384
|
+
items: external_exports.discriminatedUnion("type", [V2_LEAVES.items, groupItems])
|
|
12385
|
+
}),
|
|
12386
|
+
/**
|
|
12387
|
+
* A group of related settings.
|
|
12388
|
+
*
|
|
12389
|
+
* NO `default`. A container cannot carry one, structurally — `.strict()`
|
|
12390
|
+
* refuses the key — and that removes a whole class of question rather than
|
|
12391
|
+
* answering it: what a whole-subtree default means when the customer
|
|
12392
|
+
* supplied half of it, how it interacts with `dependentRequired`'s
|
|
12393
|
+
* load-bearing "a defaulted setting is never absent", and what
|
|
12394
|
+
* `seedConfiguration` should write into a served example and a file on
|
|
12395
|
+
* disk. Defaults are a LEAF concept here.
|
|
12396
|
+
*/
|
|
12397
|
+
external_exports.object({
|
|
12398
|
+
type: external_exports.literal("object"),
|
|
12399
|
+
title: TitleSchema,
|
|
12400
|
+
description: helpTextSchema(V2_LEAF_BOUNDS).optional(),
|
|
12401
|
+
// INHERITED BELOW THE ROOT, for the reason `V2_NESTED_LEAVES` states: a
|
|
12402
|
+
// group is a bucket for a whole subtree, and repeating it is the only
|
|
12403
|
+
// value that could be written.
|
|
12404
|
+
group: levelsBelow === MAX_CONFIGURATION_DEPTH - 1 ? ConfigurationGroupSchema : ConfigurationGroupSchema.optional(),
|
|
12405
|
+
...bag
|
|
12406
|
+
}).strict()
|
|
12407
|
+
];
|
|
12408
|
+
}
|
|
12409
|
+
var RootConfigurationPropertySchema = external_exports.discriminatedUnion("type", propertyUnion(MAX_CONFIGURATION_DEPTH - 1, V2_LEAVES));
|
|
12296
12410
|
var CustomerConfigurationObjectSchema = external_exports.object({
|
|
12297
12411
|
type: external_exports.literal("object"),
|
|
12298
12412
|
properties: external_exports.record(PropertyNameSchema, ConfigurationPropertySchema).describe("Customer-editable settings, keyed by camelCase property name."),
|
|
@@ -12326,7 +12440,6 @@ var CustomerConfigurationObjectSchema = external_exports.object({
|
|
|
12326
12440
|
*/
|
|
12327
12441
|
additionalProperties: external_exports.literal(false)
|
|
12328
12442
|
}).strict();
|
|
12329
|
-
var MAX_CONFIGURATION_PROPERTIES = 40;
|
|
12330
12443
|
var CustomerConfigurationSchema = CustomerConfigurationObjectSchema.superRefine((config, ctx) => {
|
|
12331
12444
|
const names = Object.keys(config.properties);
|
|
12332
12445
|
if (names.length > MAX_CONFIGURATION_PROPERTIES) {
|
|
@@ -12338,195 +12451,205 @@ var CustomerConfigurationSchema = CustomerConfigurationObjectSchema.superRefine(
|
|
|
12338
12451
|
}
|
|
12339
12452
|
for (const name of names) {
|
|
12340
12453
|
const property = config.properties[name];
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12454
|
+
checkDeclaredProperty(name, property, ["properties", name], ctx, true);
|
|
12455
|
+
}
|
|
12456
|
+
for (const name of config.required ?? []) {
|
|
12457
|
+
if (!Object.hasOwn(config.properties, name)) {
|
|
12344
12458
|
ctx.addIssue({
|
|
12345
12459
|
code: external_exports.ZodIssueCode.custom,
|
|
12346
|
-
path,
|
|
12347
|
-
message:
|
|
12460
|
+
path: ["required"],
|
|
12461
|
+
message: `"${name}" is listed as required but is not a declared property.`
|
|
12348
12462
|
});
|
|
12349
12463
|
}
|
|
12464
|
+
}
|
|
12465
|
+
const duplicates = (config.required ?? []).filter((name, index, all) => all.indexOf(name) !== index);
|
|
12466
|
+
if (duplicates.length > 0) {
|
|
12467
|
+
ctx.addIssue({
|
|
12468
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12469
|
+
path: ["required"],
|
|
12470
|
+
message: `Duplicate required entries: ${[...new Set(duplicates)].join(", ")}.`
|
|
12471
|
+
});
|
|
12472
|
+
}
|
|
12473
|
+
checkDependentRequired(config, ctx);
|
|
12474
|
+
});
|
|
12475
|
+
function checkDeclaredProperty(name, property, path, ctx, atRoot) {
|
|
12476
|
+
const infrastructure = infrastructureVocabularyViolation(name);
|
|
12477
|
+
if (infrastructure) {
|
|
12478
|
+
ctx.addIssue({
|
|
12479
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12480
|
+
path,
|
|
12481
|
+
message: `${infrastructure}. Customer settings describe outcomes, not infrastructure.`
|
|
12482
|
+
});
|
|
12483
|
+
}
|
|
12484
|
+
if (atRoot) {
|
|
12350
12485
|
const platformOwned = platformOwnedFieldViolation(name);
|
|
12351
12486
|
if (platformOwned) {
|
|
12352
12487
|
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message: `${platformOwned}.` });
|
|
12353
12488
|
}
|
|
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)) {
|
|
12489
|
+
}
|
|
12490
|
+
for (const [label, values] of enumerableValues(property)) {
|
|
12491
|
+
for (const value of values) {
|
|
12492
|
+
const violation = infrastructureValueViolation(value);
|
|
12493
|
+
if (violation) {
|
|
12433
12494
|
ctx.addIssue({
|
|
12434
12495
|
code: external_exports.ZodIssueCode.custom,
|
|
12435
|
-
path: [...path,
|
|
12436
|
-
message:
|
|
12496
|
+
path: [...path, label],
|
|
12497
|
+
message: `${violation}. Customer settings offer outcomes, not infrastructure sizes.`
|
|
12437
12498
|
});
|
|
12438
12499
|
}
|
|
12439
12500
|
}
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12501
|
+
}
|
|
12502
|
+
if (property.type === "string") {
|
|
12503
|
+
const secret = property["x-secret"] === true;
|
|
12504
|
+
const credential = credentialNameViolation(name);
|
|
12505
|
+
if (credential && !secret) {
|
|
12506
|
+
ctx.addIssue({
|
|
12507
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12508
|
+
path,
|
|
12509
|
+
// THE REMEDIATION HAS TO BE ONE THE CONTRACT ALLOWS. At the root, the
|
|
12510
|
+
// answer is to declare the two markers. Below it, that answer is
|
|
12511
|
+
// IMPOSSIBLE — the nested shape omits both keys and `.strict()` refuses
|
|
12512
|
+
// them — so telling a publisher to add them sends them to write a
|
|
12513
|
+
// second invalid document, and an agent following the validator loops.
|
|
12514
|
+
// A validator's errors are part of the agent-facing contract.
|
|
12515
|
+
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.`
|
|
12516
|
+
});
|
|
12517
|
+
}
|
|
12518
|
+
if (secret && property.writeOnly !== true) {
|
|
12519
|
+
ctx.addIssue({
|
|
12520
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12521
|
+
path,
|
|
12522
|
+
message: `"${name}" is marked x-secret but not writeOnly \u2014 a read API could echo the value.`
|
|
12523
|
+
});
|
|
12524
|
+
}
|
|
12525
|
+
if (property.writeOnly === true && !secret) {
|
|
12526
|
+
ctx.addIssue({
|
|
12527
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12528
|
+
path,
|
|
12529
|
+
message: `"${name}" is marked writeOnly but not x-secret \u2014 the value would not be routed to the secret flow.`
|
|
12530
|
+
});
|
|
12531
|
+
}
|
|
12532
|
+
if (secret && property.default !== void 0) {
|
|
12533
|
+
ctx.addIssue({
|
|
12534
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12535
|
+
path: [...path, "default"],
|
|
12536
|
+
message: `"${name}" is a secret and must not declare a default value.`
|
|
12537
|
+
});
|
|
12538
|
+
}
|
|
12539
|
+
if (secret && property.enum !== void 0) {
|
|
12540
|
+
ctx.addIssue({
|
|
12541
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12542
|
+
path: [...path, "enum"],
|
|
12543
|
+
message: `"${name}" is a secret; an enum would enumerate candidate secret values.`
|
|
12544
|
+
});
|
|
12545
|
+
}
|
|
12546
|
+
if (property.enum === void 0 && property.maxLength === void 0) {
|
|
12547
|
+
ctx.addIssue({
|
|
12548
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12549
|
+
path,
|
|
12550
|
+
message: `"${name}" must declare either an enum or a maxLength.`
|
|
12551
|
+
});
|
|
12552
|
+
}
|
|
12553
|
+
if (property.enum !== void 0 && property.default !== void 0 && !property.enum.includes(property.default)) {
|
|
12554
|
+
ctx.addIssue({
|
|
12555
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12556
|
+
path: [...path, "default"],
|
|
12557
|
+
message: `"${name}" declares a default outside its enum.`
|
|
12558
|
+
});
|
|
12559
|
+
}
|
|
12560
|
+
if (property.minLength !== void 0 && property.maxLength !== void 0 && property.minLength > property.maxLength) {
|
|
12561
|
+
ctx.addIssue({
|
|
12562
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12563
|
+
path,
|
|
12564
|
+
message: `"${name}" has minLength greater than maxLength.`
|
|
12565
|
+
});
|
|
12566
|
+
}
|
|
12567
|
+
if (property.default !== void 0 && property.maxLength !== void 0 && property.default.length > property.maxLength) {
|
|
12568
|
+
ctx.addIssue({
|
|
12569
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12570
|
+
path: [...path, "default"],
|
|
12571
|
+
message: `"${name}" declares a default longer than its own maxLength.`
|
|
12572
|
+
});
|
|
12573
|
+
}
|
|
12574
|
+
if (property.pattern !== void 0 && !isSafeRegex(property.pattern)) {
|
|
12575
|
+
ctx.addIssue({
|
|
12576
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12577
|
+
path: [...path, "pattern"],
|
|
12578
|
+
message: `"${name}" declares a pattern that is not a valid regular expression.`
|
|
12579
|
+
});
|
|
12580
|
+
}
|
|
12581
|
+
}
|
|
12582
|
+
if (property.type === "integer" || property.type === "number") {
|
|
12583
|
+
if (property.minimum > property.maximum) {
|
|
12584
|
+
ctx.addIssue({
|
|
12585
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12586
|
+
path,
|
|
12587
|
+
message: `"${name}" has minimum greater than maximum.`
|
|
12588
|
+
});
|
|
12589
|
+
}
|
|
12590
|
+
if (property.default !== void 0 && (property.default < property.minimum || property.default > property.maximum)) {
|
|
12591
|
+
ctx.addIssue({
|
|
12592
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12593
|
+
path: [...path, "default"],
|
|
12594
|
+
message: `"${name}" declares a default outside its minimum/maximum range.`
|
|
12595
|
+
});
|
|
12596
|
+
}
|
|
12597
|
+
if (property.type === "integer" && !Number.isInteger(property.default ?? 0)) {
|
|
12598
|
+
ctx.addIssue({
|
|
12599
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12600
|
+
path: [...path, "default"],
|
|
12601
|
+
message: `"${name}" is an integer but declares a fractional default.`
|
|
12602
|
+
});
|
|
12603
|
+
}
|
|
12604
|
+
}
|
|
12605
|
+
if (property.type === "array") {
|
|
12606
|
+
const allowed = property.items.enum;
|
|
12607
|
+
if (allowed === void 0 && property.items.maxLength === void 0) {
|
|
12608
|
+
ctx.addIssue({
|
|
12609
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12610
|
+
path: [...path, "items"],
|
|
12611
|
+
message: `"${name}" items must declare either an enum or a maxLength.`
|
|
12612
|
+
});
|
|
12613
|
+
}
|
|
12614
|
+
if (property.minItems !== void 0 && property.minItems > property.maxItems) {
|
|
12615
|
+
ctx.addIssue({
|
|
12616
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12617
|
+
path,
|
|
12618
|
+
message: `"${name}" has minItems greater than maxItems.`
|
|
12619
|
+
});
|
|
12620
|
+
}
|
|
12621
|
+
if (property.default !== void 0) {
|
|
12622
|
+
if (property.default.length > property.maxItems) {
|
|
12449
12623
|
ctx.addIssue({
|
|
12450
12624
|
code: external_exports.ZodIssueCode.custom,
|
|
12451
12625
|
path: [...path, "default"],
|
|
12452
|
-
message: `"${name}" declares a default
|
|
12626
|
+
message: `"${name}" declares a default longer than maxItems.`
|
|
12453
12627
|
});
|
|
12454
12628
|
}
|
|
12455
|
-
|
|
12629
|
+
const outside = allowed ? property.default.filter((value) => !allowed.includes(value)) : [];
|
|
12630
|
+
if (outside.length > 0) {
|
|
12456
12631
|
ctx.addIssue({
|
|
12457
12632
|
code: external_exports.ZodIssueCode.custom,
|
|
12458
12633
|
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.`
|
|
12634
|
+
message: `"${name}" declares default values outside its items enum: ${outside.join(", ")}.`
|
|
12477
12635
|
});
|
|
12478
12636
|
}
|
|
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
12637
|
}
|
|
12497
12638
|
}
|
|
12498
|
-
|
|
12499
|
-
|
|
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
|
-
});
|
|
12517
|
-
function checkDependentRequired(config, ctx) {
|
|
12639
|
+
}
|
|
12640
|
+
function checkDependentRequired(config, ctx, at = []) {
|
|
12518
12641
|
const clauses = Object.entries(config.dependentRequired ?? {});
|
|
12519
12642
|
if (clauses.length === 0)
|
|
12520
12643
|
return;
|
|
12521
12644
|
if (clauses.length > MAX_CONFIGURATION_PROPERTIES) {
|
|
12522
12645
|
ctx.addIssue({
|
|
12523
12646
|
code: external_exports.ZodIssueCode.custom,
|
|
12524
|
-
path: ["dependentRequired"],
|
|
12647
|
+
path: [...at, "dependentRequired"],
|
|
12525
12648
|
message: `A Product may declare at most ${MAX_CONFIGURATION_PROPERTIES} dependent-required groups; found ${clauses.length}.`
|
|
12526
12649
|
});
|
|
12527
12650
|
}
|
|
12528
12651
|
for (const [trigger, dependents] of clauses) {
|
|
12529
|
-
const path = ["dependentRequired", trigger];
|
|
12652
|
+
const path = [...at, "dependentRequired", trigger];
|
|
12530
12653
|
const declaredTrigger = config.properties[trigger];
|
|
12531
12654
|
if (declaredTrigger === void 0) {
|
|
12532
12655
|
ctx.addIssue({
|
|
@@ -12635,42 +12758,424 @@ function checkOneSecretPerGroup(config, ctx) {
|
|
|
12635
12758
|
});
|
|
12636
12759
|
}
|
|
12637
12760
|
}
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12761
|
+
var CustomerConfigurationV2ObjectSchema = external_exports.object({
|
|
12762
|
+
type: external_exports.literal("object"),
|
|
12763
|
+
properties: external_exports.record(PropertyNameSchema, RootConfigurationPropertySchema).describe("Customer-editable settings, keyed by camelCase property name."),
|
|
12764
|
+
required: external_exports.array(PropertyNameSchema).max(MAX_CONFIGURATION_CHILDREN).optional(),
|
|
12765
|
+
/**
|
|
12766
|
+
* ROOT PROPERTIES ONLY, in v2.0.
|
|
12767
|
+
*
|
|
12768
|
+
* The published key promises that "a publisher running an off-the-shelf
|
|
12769
|
+
* validator over that file must get the answer the platform gives", and
|
|
12770
|
+
* JSON Schema 2020-12 `dependentRequired` is scoped to the object that
|
|
12771
|
+
* carries it. A clause naming a nested leaf would be a rule no standard
|
|
12772
|
+
* validator applies, which is the one thing this key may not become. A
|
|
12773
|
+
* nested object may not carry its own clause either — that is expressible
|
|
12774
|
+
* and honest, and it is deliberately left for when something needs it.
|
|
12775
|
+
*/
|
|
12776
|
+
dependentRequired: external_exports.record(PropertyNameSchema, external_exports.array(PropertyNameSchema).min(1).max(MAX_CONFIGURATION_CHILDREN)).optional().describe("Settings that must be supplied together, keyed by the triggering property."),
|
|
12777
|
+
additionalProperties: external_exports.literal(false)
|
|
12778
|
+
}).strict();
|
|
12779
|
+
function countNodes(property) {
|
|
12780
|
+
const children = childrenOf(property);
|
|
12781
|
+
if (children === null)
|
|
12782
|
+
return { leaves: 1, nodes: 1, instantiated: 1 };
|
|
12783
|
+
let leaves = 0;
|
|
12784
|
+
let nodes = 1;
|
|
12785
|
+
let instantiated = 0;
|
|
12786
|
+
for (const child of Object.values(children.properties)) {
|
|
12787
|
+
const inner = countNodes(child);
|
|
12788
|
+
leaves += inner.leaves;
|
|
12789
|
+
nodes += inner.nodes;
|
|
12790
|
+
instantiated += inner.instantiated;
|
|
12791
|
+
}
|
|
12792
|
+
if (property.type === "array")
|
|
12793
|
+
instantiated *= property.maxItems;
|
|
12794
|
+
return { leaves, nodes, instantiated };
|
|
12795
|
+
}
|
|
12796
|
+
function childrenOf(property) {
|
|
12797
|
+
if (property.type === "object")
|
|
12798
|
+
return property;
|
|
12799
|
+
if (property.type === "array" && property.items.type === "object")
|
|
12800
|
+
return property.items;
|
|
12801
|
+
return null;
|
|
12802
|
+
}
|
|
12803
|
+
function minimumConfigurationBytes(config) {
|
|
12804
|
+
return minimumGroupBytes(config.properties, config.required ?? []);
|
|
12805
|
+
}
|
|
12806
|
+
function minimumGroupBytes(properties, required) {
|
|
12807
|
+
const names = new Set(required);
|
|
12808
|
+
let total = 2;
|
|
12809
|
+
for (const [name, property] of Object.entries(properties)) {
|
|
12810
|
+
const isContainer = childrenOf(property) !== null;
|
|
12811
|
+
if (isContainer ? !names.has(name) : !names.has(name) && declaredLeafDefault(property) === void 0) {
|
|
12812
|
+
continue;
|
|
12813
|
+
}
|
|
12814
|
+
total += name.length + 3 + minimumPropertyBytes(property);
|
|
12815
|
+
}
|
|
12816
|
+
return total;
|
|
12817
|
+
}
|
|
12818
|
+
function minimumPropertyBytes(property) {
|
|
12819
|
+
const children = childrenOf(property);
|
|
12820
|
+
if (children !== null) {
|
|
12821
|
+
const inner = minimumGroupBytes(children.properties, children.required ?? []);
|
|
12822
|
+
return property.type === "array" ? 2 + (property.minItems ?? 0) * inner : inner;
|
|
12823
|
+
}
|
|
12824
|
+
switch (property.type) {
|
|
12825
|
+
case "string": {
|
|
12826
|
+
const shortestEnum = property.enum?.reduce((a, b) => a.length <= b.length ? a : b);
|
|
12827
|
+
const shortest = shortestEnum?.length ?? Math.max(property.minLength ?? 0, 1);
|
|
12828
|
+
return shortest + 2;
|
|
12829
|
+
}
|
|
12830
|
+
case "integer":
|
|
12831
|
+
case "number":
|
|
12832
|
+
return 1;
|
|
12833
|
+
case "boolean":
|
|
12834
|
+
return 4;
|
|
12835
|
+
case "array":
|
|
12836
|
+
return 2 + (property.minItems ?? 0) * 3;
|
|
12837
|
+
case "object":
|
|
12838
|
+
return 2;
|
|
12839
|
+
}
|
|
12840
|
+
}
|
|
12841
|
+
function declaredLeafDefault(property) {
|
|
12842
|
+
return property.type === "object" ? void 0 : property.default;
|
|
12843
|
+
}
|
|
12844
|
+
function checkPropertyDeclaration(name, property, path, ctx, atRoot) {
|
|
12845
|
+
const children = childrenOf(property);
|
|
12846
|
+
if (children === null) {
|
|
12847
|
+
checkDeclaredProperty(name, property, path, ctx, atRoot);
|
|
12848
|
+
return;
|
|
12849
|
+
}
|
|
12850
|
+
const infrastructure = infrastructureVocabularyViolation(name);
|
|
12851
|
+
if (infrastructure) {
|
|
12852
|
+
ctx.addIssue({
|
|
12853
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12854
|
+
path,
|
|
12855
|
+
message: `${infrastructure}. Customer settings describe outcomes, not infrastructure.`
|
|
12856
|
+
});
|
|
12857
|
+
}
|
|
12858
|
+
if (atRoot) {
|
|
12859
|
+
const platformOwned = platformOwnedFieldViolation(name);
|
|
12860
|
+
if (platformOwned) {
|
|
12861
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message: `${platformOwned}.` });
|
|
12862
|
+
}
|
|
12863
|
+
}
|
|
12864
|
+
const childNames = Object.keys(children.properties);
|
|
12865
|
+
if (childNames.length === 0) {
|
|
12866
|
+
ctx.addIssue({
|
|
12867
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12868
|
+
path: [...path, "properties"],
|
|
12869
|
+
message: `"${name}" declares no settings. A group with nothing in it renders as an empty section.`
|
|
12870
|
+
});
|
|
12871
|
+
}
|
|
12872
|
+
if (childNames.length > MAX_CONFIGURATION_CHILDREN) {
|
|
12873
|
+
ctx.addIssue({
|
|
12874
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12875
|
+
path: [...path, "properties"],
|
|
12876
|
+
message: `"${name}" may declare at most ${MAX_CONFIGURATION_CHILDREN} settings; found ${childNames.length}.`
|
|
12877
|
+
});
|
|
12878
|
+
}
|
|
12879
|
+
if (property.type === "array" && property.default !== void 0) {
|
|
12880
|
+
ctx.addIssue({
|
|
12881
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12882
|
+
path: [...path, "default"],
|
|
12883
|
+
message: `"${name}" is a list of groups and cannot declare a default. Declare defaults on the settings inside it.`
|
|
12884
|
+
});
|
|
12885
|
+
}
|
|
12886
|
+
if (property.type === "array" && property.minItems !== void 0 && property.minItems > property.maxItems) {
|
|
12887
|
+
ctx.addIssue({
|
|
12888
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12889
|
+
path,
|
|
12890
|
+
message: `"${name}" has minItems greater than maxItems.`
|
|
12891
|
+
});
|
|
12892
|
+
}
|
|
12893
|
+
for (const childName of childNames) {
|
|
12894
|
+
checkPropertyDeclaration(childName, children.properties[childName], [...path, "properties", childName], ctx, false);
|
|
12895
|
+
}
|
|
12896
|
+
for (const required of children.required ?? []) {
|
|
12897
|
+
if (!Object.hasOwn(children.properties, required)) {
|
|
12898
|
+
ctx.addIssue({
|
|
12899
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12900
|
+
path: [...path, "required"],
|
|
12901
|
+
message: `"${required}" is listed as required in "${name}" but is not one of its settings.`
|
|
12902
|
+
});
|
|
12903
|
+
}
|
|
12904
|
+
}
|
|
12905
|
+
const scoped = children;
|
|
12906
|
+
if (scoped.dependentRequired !== void 0) {
|
|
12907
|
+
checkDependentRequired(
|
|
12908
|
+
{ properties: children.properties, dependentRequired: scoped.dependentRequired },
|
|
12909
|
+
ctx,
|
|
12910
|
+
// An ARRAY's children live under `items`, which is where the key it
|
|
12911
|
+
// constrains actually sits in the document.
|
|
12912
|
+
property.type === "array" ? [...path, "items"] : path
|
|
12913
|
+
);
|
|
12914
|
+
}
|
|
12915
|
+
}
|
|
12916
|
+
var CustomerConfigurationV2Schema = CustomerConfigurationV2ObjectSchema.superRefine((config, ctx) => {
|
|
12917
|
+
const names = Object.keys(config.properties);
|
|
12918
|
+
if (names.length > MAX_CONFIGURATION_CHILDREN) {
|
|
12919
|
+
ctx.addIssue({
|
|
12920
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12921
|
+
path: ["properties"],
|
|
12922
|
+
message: `A Product may declare at most ${MAX_CONFIGURATION_CHILDREN} root settings; found ${names.length}. Group them, or declare fewer.`
|
|
12923
|
+
});
|
|
12924
|
+
}
|
|
12925
|
+
let leaves = 0;
|
|
12926
|
+
let nodes = 0;
|
|
12927
|
+
let instantiated = 0;
|
|
12928
|
+
for (const name of names) {
|
|
12929
|
+
const property = config.properties[name];
|
|
12930
|
+
const path = ["properties", name];
|
|
12931
|
+
const counted = countNodes(property);
|
|
12932
|
+
leaves += counted.leaves;
|
|
12933
|
+
nodes += counted.nodes;
|
|
12934
|
+
instantiated += counted.instantiated;
|
|
12935
|
+
checkPropertyDeclaration(name, property, path, ctx, true);
|
|
12936
|
+
}
|
|
12937
|
+
if (leaves > MAX_CONFIGURATION_LEAVES) {
|
|
12938
|
+
ctx.addIssue({
|
|
12939
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12940
|
+
path: ["properties"],
|
|
12941
|
+
message: `A Product may declare at most ${MAX_CONFIGURATION_LEAVES} customer settings in total; found ${leaves}.`
|
|
12942
|
+
});
|
|
12943
|
+
}
|
|
12944
|
+
if (nodes > MAX_CONFIGURATION_NODES) {
|
|
12945
|
+
ctx.addIssue({
|
|
12946
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12947
|
+
path: ["properties"],
|
|
12948
|
+
message: `A Product may declare at most ${MAX_CONFIGURATION_NODES} configuration nodes; found ${nodes}.`
|
|
12949
|
+
});
|
|
12950
|
+
}
|
|
12951
|
+
if (instantiated > MAX_CONFIGURATION_VALUE_LEAVES) {
|
|
12952
|
+
ctx.addIssue({
|
|
12953
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12954
|
+
path: ["properties"],
|
|
12955
|
+
message: `This Product's settings could expand to ${instantiated} values. A list instantiates everything inside it once per item, so lists inside lists MULTIPLY. At most ${MAX_CONFIGURATION_VALUE_LEAVES} are allowed; reduce maxItems on the lists, or the number of settings inside them.`
|
|
12956
|
+
});
|
|
12957
|
+
}
|
|
12958
|
+
for (const name of config.required ?? []) {
|
|
12959
|
+
if (!Object.hasOwn(config.properties, name)) {
|
|
12960
|
+
ctx.addIssue({
|
|
12961
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12962
|
+
path: ["required"],
|
|
12963
|
+
message: `"${name}" is listed as required but is not a declared property.`
|
|
12964
|
+
});
|
|
12965
|
+
}
|
|
12966
|
+
}
|
|
12967
|
+
const floor = minimumConfigurationBytes(config);
|
|
12968
|
+
if (floor > MAX_CONFIGURATION_VALUE_BYTES) {
|
|
12969
|
+
ctx.addIssue({
|
|
12970
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12971
|
+
path: ["properties"],
|
|
12972
|
+
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.`
|
|
12973
|
+
});
|
|
12974
|
+
}
|
|
12975
|
+
checkDependentRequired(config, ctx);
|
|
12976
|
+
checkOneSecretPerGroup(config, ctx);
|
|
12977
|
+
});
|
|
12978
|
+
function enumerableValues(property) {
|
|
12979
|
+
const out = [];
|
|
12980
|
+
if (property.type === "string") {
|
|
12981
|
+
if (property.enum)
|
|
12982
|
+
out.push(["enum", property.enum]);
|
|
12983
|
+
if (property.default !== void 0)
|
|
12984
|
+
out.push(["default", [property.default]]);
|
|
12985
|
+
}
|
|
12986
|
+
if (property.type === "array") {
|
|
12987
|
+
if (property.items.enum)
|
|
12988
|
+
out.push(["items", property.items.enum]);
|
|
12989
|
+
if (property.default)
|
|
12990
|
+
out.push(["default", property.default]);
|
|
12991
|
+
}
|
|
12992
|
+
return out;
|
|
12993
|
+
}
|
|
12994
|
+
function isSafeRegex(pattern) {
|
|
12995
|
+
try {
|
|
12996
|
+
new RegExp(pattern);
|
|
12997
|
+
return true;
|
|
12998
|
+
} catch {
|
|
12999
|
+
return false;
|
|
13000
|
+
}
|
|
13001
|
+
}
|
|
13002
|
+
function isSecretProperty(property) {
|
|
13003
|
+
return property.type === "string" && property["x-secret"] === true;
|
|
13004
|
+
}
|
|
13005
|
+
|
|
13006
|
+
// ../product-configuration/dist/configuration-path.js
|
|
13007
|
+
var MAX_CONFIGURATION_PATH_SEGMENTS = 2 * MAX_CONFIGURATION_DEPTH - 1;
|
|
13008
|
+
function isIndexSegment(raw) {
|
|
13009
|
+
return /^\d+$/.test(raw) && String(Number(raw)) === raw;
|
|
13010
|
+
}
|
|
13011
|
+
function isPathSegment(segment) {
|
|
13012
|
+
if (typeof segment === "number")
|
|
13013
|
+
return Number.isInteger(segment) && segment >= 0;
|
|
13014
|
+
return CONFIGURATION_PROPERTY_NAME_REGEX.test(segment) || isIndexSegment(segment);
|
|
13015
|
+
}
|
|
13016
|
+
function configurationPath(...segments) {
|
|
13017
|
+
if (segments.length === 0 || segments.length > MAX_CONFIGURATION_PATH_SEGMENTS)
|
|
13018
|
+
return null;
|
|
13019
|
+
if (!segments.every(isPathSegment))
|
|
13020
|
+
return null;
|
|
13021
|
+
if (typeof segments[0] === "number" || isIndexSegment(String(segments[0])))
|
|
13022
|
+
return null;
|
|
13023
|
+
if (segments.length === 1)
|
|
13024
|
+
return String(segments[0]);
|
|
13025
|
+
return `/${segments.map(String).join("/")}`;
|
|
13026
|
+
}
|
|
13027
|
+
function parseConfigurationPath(raw) {
|
|
13028
|
+
if (typeof raw !== "string" || raw.length === 0)
|
|
13029
|
+
return null;
|
|
13030
|
+
if (!raw.startsWith("/"))
|
|
13031
|
+
return configurationPath(raw);
|
|
13032
|
+
const segments = raw.slice(1).split("/");
|
|
13033
|
+
if (segments.length < 2)
|
|
13034
|
+
return null;
|
|
13035
|
+
return configurationPath(...segments);
|
|
13036
|
+
}
|
|
13037
|
+
function pathSegments(path) {
|
|
13038
|
+
const raw = path.startsWith("/") ? path.slice(1).split("/") : [path];
|
|
13039
|
+
return raw.map((segment) => isIndexSegment(segment) ? Number(segment) : segment);
|
|
13040
|
+
}
|
|
13041
|
+
function declarationPathOf(path) {
|
|
13042
|
+
const segments = pathSegments(path).filter((segment) => typeof segment !== "number");
|
|
13043
|
+
return configurationPath(...segments) ?? path;
|
|
13044
|
+
}
|
|
13045
|
+
function printableConfigurationPath(path) {
|
|
13046
|
+
return pathSegments(path).join(".");
|
|
13047
|
+
}
|
|
13048
|
+
|
|
13049
|
+
// ../product-configuration/dist/canonical-json.js
|
|
13050
|
+
function canonicalise(value, path) {
|
|
13051
|
+
if (value === null)
|
|
13052
|
+
return "null";
|
|
13053
|
+
if (typeof value === "string")
|
|
13054
|
+
return JSON.stringify(value);
|
|
13055
|
+
if (typeof value === "boolean")
|
|
13056
|
+
return value ? "true" : "false";
|
|
13057
|
+
if (typeof value === "number") {
|
|
13058
|
+
if (!Number.isFinite(value)) {
|
|
13059
|
+
throw new Error(`canonicalJson: non-finite number at ${path}`);
|
|
13060
|
+
}
|
|
13061
|
+
return JSON.stringify(value === 0 ? 0 : value);
|
|
13062
|
+
}
|
|
13063
|
+
if (typeof value !== "object") {
|
|
13064
|
+
throw new Error(`canonicalJson: ${typeof value} is not JSON at ${path}`);
|
|
13065
|
+
}
|
|
13066
|
+
if (Array.isArray(value)) {
|
|
13067
|
+
return `[${value.map((item, i) => canonicalise(item, `${path}[${i}]`)).join(",")}]`;
|
|
13068
|
+
}
|
|
13069
|
+
const entries = Object.entries(value);
|
|
13070
|
+
for (const [key, item] of entries) {
|
|
13071
|
+
if (item === void 0) {
|
|
13072
|
+
throw new Error(`canonicalJson: undefined property at ${path}.${key}`);
|
|
13073
|
+
}
|
|
13074
|
+
}
|
|
13075
|
+
const sorted = entries.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
13076
|
+
const body = sorted.map(([key, item]) => `${JSON.stringify(key)}:${canonicalise(item, `${path}.${key}`)}`).join(",");
|
|
13077
|
+
return `{${body}}`;
|
|
13078
|
+
}
|
|
13079
|
+
function canonicalJson(value) {
|
|
13080
|
+
return canonicalise(value, "$");
|
|
13081
|
+
}
|
|
13082
|
+
|
|
13083
|
+
// ../product-configuration/dist/configuration-tree.js
|
|
13084
|
+
function underList(node) {
|
|
13085
|
+
return node.containers.some((container) => container.kind === "array");
|
|
13086
|
+
}
|
|
13087
|
+
function containerChildren(property) {
|
|
13088
|
+
if (property.type === "object" && property.properties !== void 0) {
|
|
13089
|
+
return {
|
|
13090
|
+
kind: "object",
|
|
13091
|
+
properties: property.properties,
|
|
13092
|
+
required: property.required ?? []
|
|
13093
|
+
};
|
|
12645
13094
|
}
|
|
12646
|
-
if (property.type === "array") {
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
13095
|
+
if (property.type === "array" && property.items !== void 0) {
|
|
13096
|
+
const items = property.items;
|
|
13097
|
+
if (items.type !== "object" || items.properties === void 0)
|
|
13098
|
+
return null;
|
|
13099
|
+
return {
|
|
13100
|
+
kind: "array",
|
|
13101
|
+
properties: items.properties,
|
|
13102
|
+
required: items.required ?? []
|
|
13103
|
+
};
|
|
12651
13104
|
}
|
|
13105
|
+
return null;
|
|
13106
|
+
}
|
|
13107
|
+
function isConfigurationContainer(property) {
|
|
13108
|
+
return containerChildren(property) !== null;
|
|
13109
|
+
}
|
|
13110
|
+
function configurationLeaves(schema) {
|
|
13111
|
+
const out = [];
|
|
13112
|
+
walkDeclarations(schema.properties, [], [], (leaf) => out.push(leaf));
|
|
12652
13113
|
return out;
|
|
12653
13114
|
}
|
|
12654
|
-
function
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
13115
|
+
function configurationContainers(schema) {
|
|
13116
|
+
const out = [];
|
|
13117
|
+
walkDeclarations(schema.properties, [], [], () => {
|
|
13118
|
+
}, (container) => out.push(container));
|
|
13119
|
+
return out;
|
|
13120
|
+
}
|
|
13121
|
+
function walkDeclarations(properties, ancestors, base, onLeaf, onContainer = () => {
|
|
13122
|
+
}) {
|
|
13123
|
+
for (const [name, property] of Object.entries(properties)) {
|
|
13124
|
+
const segments = [...base, name];
|
|
13125
|
+
const path = configurationPath(...segments);
|
|
13126
|
+
if (path === null)
|
|
13127
|
+
continue;
|
|
13128
|
+
const children = containerChildren(property);
|
|
13129
|
+
if (children === null) {
|
|
13130
|
+
onLeaf({ path, name, property, containers: ancestors });
|
|
13131
|
+
continue;
|
|
13132
|
+
}
|
|
13133
|
+
const container = {
|
|
13134
|
+
path,
|
|
13135
|
+
name,
|
|
13136
|
+
kind: children.kind,
|
|
13137
|
+
property,
|
|
13138
|
+
required: children.required,
|
|
13139
|
+
containers: ancestors
|
|
13140
|
+
};
|
|
13141
|
+
onContainer(container);
|
|
13142
|
+
walkDeclarations(children.properties, [...ancestors, container], segments, onLeaf, onContainer);
|
|
12660
13143
|
}
|
|
12661
13144
|
}
|
|
13145
|
+
function leafAt(schema, path) {
|
|
13146
|
+
const declaration = declarationPathOf(path);
|
|
13147
|
+
return configurationLeaves(schema).find((leaf) => leaf.path === declaration) ?? null;
|
|
13148
|
+
}
|
|
13149
|
+
function declaresPath(schema, path) {
|
|
13150
|
+
if (leafAt(schema, path) !== null)
|
|
13151
|
+
return true;
|
|
13152
|
+
return configurationContainers(schema).some((container) => container.path === declarationPathOf(path));
|
|
13153
|
+
}
|
|
12662
13154
|
|
|
12663
13155
|
// ../product-configuration/dist/customer-configuration-input.js
|
|
12664
|
-
var ABSOLUTE_MAX_STRING =
|
|
13156
|
+
var ABSOLUTE_MAX_STRING = MAX_DECLARABLE_STRING_LENGTH;
|
|
12665
13157
|
var MAX_REPORTED_UNDECLARED_KEYS = 10;
|
|
12666
13158
|
function isPlainObject(value) {
|
|
12667
13159
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12668
13160
|
}
|
|
12669
|
-
function
|
|
12670
|
-
|
|
13161
|
+
function report(walk, field, message) {
|
|
13162
|
+
if (walk.issues.length >= MAX_CONFIGURATION_ISSUES) {
|
|
13163
|
+
walk.suppressed += 1;
|
|
13164
|
+
return;
|
|
13165
|
+
}
|
|
13166
|
+
walk.issues.push({ field, message });
|
|
13167
|
+
}
|
|
13168
|
+
function drain(walk, collected) {
|
|
13169
|
+
for (const issue of collected)
|
|
13170
|
+
report(walk, issue.field, issue.message);
|
|
12671
13171
|
}
|
|
12672
13172
|
function validateSubmittedConfiguration(schema, submitted, presence = {}) {
|
|
12673
|
-
const
|
|
13173
|
+
const walk = {
|
|
13174
|
+
issues: [],
|
|
13175
|
+
suppressed: 0,
|
|
13176
|
+
leaves: 0,
|
|
13177
|
+
referenced: new Set(presence.referenced ?? [])
|
|
13178
|
+
};
|
|
12674
13179
|
const supplied = /* @__PURE__ */ new Set();
|
|
12675
13180
|
if (submitted !== void 0 && submitted !== null && !isPlainObject(submitted)) {
|
|
12676
13181
|
return {
|
|
@@ -12680,64 +13185,211 @@ function validateSubmittedConfiguration(schema, submitted, presence = {}) {
|
|
|
12680
13185
|
};
|
|
12681
13186
|
}
|
|
12682
13187
|
const input = isPlainObject(submitted) ? submitted : {};
|
|
12683
|
-
const
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
|
|
12688
|
-
});
|
|
12689
|
-
}
|
|
12690
|
-
if (undeclared.length > MAX_REPORTED_UNDECLARED_KEYS) {
|
|
12691
|
-
issues.push({
|
|
13188
|
+
const secrets = {};
|
|
13189
|
+
const configuration = validateObject({ properties: schema.properties, required: schema.required }, input, null, walk, { secrets, supplied });
|
|
13190
|
+
drain(walk, crossFieldIssues(schema, supplied, presence));
|
|
13191
|
+
if (walk.suppressed > 0) {
|
|
13192
|
+
walk.issues.push({
|
|
12692
13193
|
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.`
|
|
13194
|
+
message: `${walk.suppressed} further problems were found and are not listed.`
|
|
12696
13195
|
});
|
|
12697
13196
|
}
|
|
12698
|
-
|
|
12699
|
-
|
|
12700
|
-
|
|
12701
|
-
|
|
12702
|
-
|
|
12703
|
-
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
13197
|
+
if (declaresContainer(schema)) {
|
|
13198
|
+
const size = utf8ByteLength(JSON.stringify(configuration));
|
|
13199
|
+
if (size > MAX_CONFIGURATION_VALUE_BYTES) {
|
|
13200
|
+
report(walk, "", `This configuration is ${size} bytes once defaults are applied, and the limit is ${MAX_CONFIGURATION_VALUE_BYTES}. Remove some items.`);
|
|
13201
|
+
}
|
|
13202
|
+
}
|
|
13203
|
+
if (walk.issues.length > 0)
|
|
13204
|
+
return { ok: false, issues: walk.issues, partial: configuration };
|
|
13205
|
+
return { ok: true, configuration, secrets };
|
|
13206
|
+
}
|
|
13207
|
+
function utf8ByteLength(value) {
|
|
13208
|
+
return new TextEncoder().encode(value).length;
|
|
13209
|
+
}
|
|
13210
|
+
function declaresContainer(schema) {
|
|
13211
|
+
return Object.values(schema.properties).some((property) => isConfigurationContainer(property));
|
|
13212
|
+
}
|
|
13213
|
+
function containsReferenced(walk, container) {
|
|
13214
|
+
if (walk.referenced.size === 0)
|
|
13215
|
+
return false;
|
|
13216
|
+
const parsedOuter = parseConfigurationPath(container);
|
|
13217
|
+
if (parsedOuter === null)
|
|
13218
|
+
return false;
|
|
13219
|
+
const outer = pathSegments(parsedOuter);
|
|
13220
|
+
for (const candidate of walk.referenced) {
|
|
13221
|
+
const parsed = parseConfigurationPath(candidate);
|
|
13222
|
+
if (parsed === null)
|
|
13223
|
+
continue;
|
|
13224
|
+
const inner = pathSegments(parsed);
|
|
13225
|
+
if (inner.length <= outer.length)
|
|
13226
|
+
continue;
|
|
13227
|
+
if (outer.every((segment, index) => inner[index] === segment))
|
|
13228
|
+
return true;
|
|
13229
|
+
}
|
|
13230
|
+
return false;
|
|
13231
|
+
}
|
|
13232
|
+
function validateObject(declaration, input, container, walk, root) {
|
|
13233
|
+
const required = new Set(declaration.required ?? []);
|
|
13234
|
+
const out = {};
|
|
13235
|
+
const fieldFor = (name) => {
|
|
13236
|
+
const path = container === null ? configurationPath(name) : configurationPath(...pathSegments(container), name);
|
|
13237
|
+
return path ?? "";
|
|
13238
|
+
};
|
|
13239
|
+
const undeclared = Object.keys(input).filter((name) => !Object.hasOwn(declaration.properties, name));
|
|
13240
|
+
for (const name of undeclared.slice(0, MAX_REPORTED_UNDECLARED_KEYS)) {
|
|
13241
|
+
report(walk, fieldFor(name), "This Product does not declare a setting with that name.");
|
|
13242
|
+
}
|
|
13243
|
+
if (undeclared.length > MAX_REPORTED_UNDECLARED_KEYS) {
|
|
13244
|
+
report(walk, container === null ? "" : container, `${undeclared.length - MAX_REPORTED_UNDECLARED_KEYS} further settings are not declared by this Product.`);
|
|
13245
|
+
}
|
|
13246
|
+
for (const [name, property] of Object.entries(declaration.properties)) {
|
|
13247
|
+
const field = fieldFor(name);
|
|
13248
|
+
const children = containerDeclaration(property);
|
|
13249
|
+
if (children !== null) {
|
|
13250
|
+
const value = input[name];
|
|
13251
|
+
const filled = validateContainer(name, property, children, value, field, walk);
|
|
13252
|
+
if (filled !== void 0)
|
|
13253
|
+
out[name] = filled;
|
|
13254
|
+
else if (required.has(name) && !containsReferenced(walk, field))
|
|
13255
|
+
report(walk, field, "This setting is required.");
|
|
13256
|
+
continue;
|
|
13257
|
+
}
|
|
13258
|
+
const leaf = property;
|
|
13259
|
+
if (walk.referenced.has(field)) {
|
|
13260
|
+
const sent = input[name];
|
|
13261
|
+
if (Object.hasOwn(input, name) && sent !== void 0) {
|
|
13262
|
+
report(walk, field, "This setting is answered by another Resource, so it cannot also be set here.");
|
|
13263
|
+
}
|
|
13264
|
+
continue;
|
|
13265
|
+
}
|
|
13266
|
+
const raw = input[name];
|
|
13267
|
+
const blank = typeof raw === "string" && raw.trim().length === 0;
|
|
13268
|
+
const present = Object.hasOwn(input, name) && raw !== void 0 && !blank;
|
|
13269
|
+
const secret = root !== null && isSecretProperty(leaf);
|
|
13270
|
+
if (present && root !== null && container === null)
|
|
13271
|
+
root.supplied.add(name);
|
|
12707
13272
|
if (!present) {
|
|
12708
|
-
const fallback = secret ? void 0 : defaultOf(
|
|
13273
|
+
const fallback = secret ? void 0 : defaultOf(leaf);
|
|
12709
13274
|
if (fallback !== void 0) {
|
|
12710
|
-
|
|
13275
|
+
walk.leaves += 1;
|
|
13276
|
+
out[name] = fallback;
|
|
12711
13277
|
} else if (required.has(name)) {
|
|
12712
|
-
|
|
13278
|
+
report(walk, field, "This setting is required.");
|
|
12713
13279
|
}
|
|
12714
13280
|
continue;
|
|
12715
13281
|
}
|
|
12716
|
-
|
|
12717
|
-
const
|
|
12718
|
-
const checked = checkProperty(
|
|
12719
|
-
if (
|
|
13282
|
+
walk.leaves += 1;
|
|
13283
|
+
const collected = [];
|
|
13284
|
+
const checked = checkProperty(field, leaf, raw, collected);
|
|
13285
|
+
if (collected.length > 0 || checked === void 0) {
|
|
13286
|
+
drain(walk, collected);
|
|
12720
13287
|
continue;
|
|
13288
|
+
}
|
|
12721
13289
|
if (secret) {
|
|
12722
13290
|
if (typeof checked === "string" && checked.length > 0)
|
|
12723
|
-
secrets[name] = checked;
|
|
12724
|
-
else if (required.has(name))
|
|
12725
|
-
|
|
13291
|
+
root.secrets[name] = checked;
|
|
13292
|
+
else if (required.has(name))
|
|
13293
|
+
report(walk, field, "This setting is required.");
|
|
13294
|
+
continue;
|
|
13295
|
+
}
|
|
13296
|
+
out[name] = checked;
|
|
13297
|
+
}
|
|
13298
|
+
if (declaration.dependentRequired !== void 0) {
|
|
13299
|
+
const suppliedHere = new Set(Object.keys(out));
|
|
13300
|
+
for (const [trigger, dependents] of Object.entries(declaration.dependentRequired)) {
|
|
13301
|
+
if (!suppliedHere.has(trigger) && !containsReferenced(walk, fieldFor(trigger)))
|
|
13302
|
+
continue;
|
|
13303
|
+
for (const dependent of dependents) {
|
|
13304
|
+
if (suppliedHere.has(dependent) || containsReferenced(walk, fieldFor(dependent)))
|
|
13305
|
+
continue;
|
|
13306
|
+
report(walk, fieldFor(dependent), `This setting is required when ${labelOf(declaration, trigger)} is configured.`);
|
|
12726
13307
|
}
|
|
13308
|
+
}
|
|
13309
|
+
}
|
|
13310
|
+
return out;
|
|
13311
|
+
}
|
|
13312
|
+
function containerDeclaration(property) {
|
|
13313
|
+
if (property.type === "object" && property.properties !== void 0) {
|
|
13314
|
+
return {
|
|
13315
|
+
kind: "object",
|
|
13316
|
+
properties: property.properties,
|
|
13317
|
+
required: property.required,
|
|
13318
|
+
// CARRIED THROUGH, or the rule the container declares is one the walk
|
|
13319
|
+
// never sees — it publishes cleanly and enforces nothing.
|
|
13320
|
+
dependentRequired: property.dependentRequired,
|
|
13321
|
+
maxItems: 1
|
|
13322
|
+
};
|
|
13323
|
+
}
|
|
13324
|
+
if (property.type === "array" && property.items !== void 0) {
|
|
13325
|
+
const items = property.items;
|
|
13326
|
+
if (items.type !== "object" || items.properties === void 0)
|
|
13327
|
+
return null;
|
|
13328
|
+
return {
|
|
13329
|
+
kind: "array",
|
|
13330
|
+
properties: items.properties,
|
|
13331
|
+
required: items.required,
|
|
13332
|
+
dependentRequired: items.dependentRequired,
|
|
13333
|
+
maxItems: property.maxItems ?? 0,
|
|
13334
|
+
minItems: property.minItems,
|
|
13335
|
+
uniqueItems: property.uniqueItems === true
|
|
13336
|
+
};
|
|
13337
|
+
}
|
|
13338
|
+
return null;
|
|
13339
|
+
}
|
|
13340
|
+
function validateContainer(name, property, children, value, field, walk) {
|
|
13341
|
+
const path = parseConfigurationPath(field);
|
|
13342
|
+
if (children.kind === "object") {
|
|
13343
|
+
if (value === void 0)
|
|
13344
|
+
return void 0;
|
|
13345
|
+
if (!isPlainObject(value)) {
|
|
13346
|
+
report(walk, field, "Expected a group of settings.");
|
|
13347
|
+
return void 0;
|
|
13348
|
+
}
|
|
13349
|
+
const filled = validateObject(children, value, path, walk, null);
|
|
13350
|
+
return Object.keys(filled).length === 0 ? void 0 : filled;
|
|
13351
|
+
}
|
|
13352
|
+
if (value === void 0)
|
|
13353
|
+
return void 0;
|
|
13354
|
+
if (!Array.isArray(value)) {
|
|
13355
|
+
report(walk, field, "Expected a list.");
|
|
13356
|
+
return void 0;
|
|
13357
|
+
}
|
|
13358
|
+
if (value.length > children.maxItems) {
|
|
13359
|
+
report(walk, field, `At most ${children.maxItems} items are allowed.`);
|
|
13360
|
+
return void 0;
|
|
13361
|
+
}
|
|
13362
|
+
if (children.minItems !== void 0 && value.length < children.minItems) {
|
|
13363
|
+
report(walk, field, `At least ${children.minItems} items are required.`);
|
|
13364
|
+
return void 0;
|
|
13365
|
+
}
|
|
13366
|
+
const out = [];
|
|
13367
|
+
for (const [index, element] of value.entries()) {
|
|
13368
|
+
if (walk.leaves >= MAX_CONFIGURATION_VALUE_LEAVES) {
|
|
13369
|
+
report(walk, field, "This configuration has too many values.");
|
|
13370
|
+
break;
|
|
13371
|
+
}
|
|
13372
|
+
if (!isPlainObject(element)) {
|
|
13373
|
+
report(walk, `${field}`, `Item ${index + 1} is not a group of settings.`);
|
|
12727
13374
|
continue;
|
|
12728
13375
|
}
|
|
12729
|
-
|
|
13376
|
+
const elementPath = path === null ? null : configurationPath(...pathSegments(path), index);
|
|
13377
|
+
out.push(validateObject(children, element, elementPath, walk, null));
|
|
12730
13378
|
}
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
|
|
13379
|
+
if (children.uniqueItems === true) {
|
|
13380
|
+
const seen = new Set(out.map((entry) => canonicalJson(entry)));
|
|
13381
|
+
if (seen.size !== out.length) {
|
|
13382
|
+
report(walk, field, "Items must be unique.");
|
|
13383
|
+
return void 0;
|
|
13384
|
+
}
|
|
13385
|
+
}
|
|
13386
|
+
return out;
|
|
12735
13387
|
}
|
|
12736
13388
|
function crossFieldIssues(schema, supplied, presence) {
|
|
12737
13389
|
const clauses = Object.entries(schema.dependentRequired ?? {});
|
|
12738
13390
|
if (clauses.length === 0)
|
|
12739
13391
|
return [];
|
|
12740
|
-
const alsoPresent = new Set(presence.present ?? []);
|
|
13392
|
+
const alsoPresent = /* @__PURE__ */ new Set([...presence.present ?? [], ...presence.referenced ?? []]);
|
|
12741
13393
|
const unknown = new Set(presence.unknown ?? []);
|
|
12742
13394
|
const known = (name) => !unknown.has(name);
|
|
12743
13395
|
const held = (name) => supplied.has(name) || alsoPresent.has(name);
|
|
@@ -12762,7 +13414,7 @@ function crossFieldIssues(schema, supplied, presence) {
|
|
|
12762
13414
|
}
|
|
12763
13415
|
function labelOf(schema, name) {
|
|
12764
13416
|
const property = schema.properties[name];
|
|
12765
|
-
return property === void 0 ? `"${name}"` : `"${property.title}"`;
|
|
13417
|
+
return property?.title === void 0 ? `"${name}"` : `"${property.title}"`;
|
|
12766
13418
|
}
|
|
12767
13419
|
function withoutCrossFieldRules(schema) {
|
|
12768
13420
|
if (schema.dependentRequired === void 0)
|
|
@@ -12905,11 +13557,11 @@ var RESOURCE_KEY_RULE = "A resource key is 3\u201363 characters of lowercase let
|
|
|
12905
13557
|
var ResourceKeySchema = external_exports.string().regex(RESOURCE_KEY_PATTERN, RESOURCE_KEY_RULE).describe(RESOURCE_KEY_RULE);
|
|
12906
13558
|
|
|
12907
13559
|
// ../product-configuration/dist/product-instance-example.js
|
|
12908
|
-
function resolveExampleChoice(options, selected,
|
|
13560
|
+
function resolveExampleChoice(options, selected, declaredDefault2) {
|
|
12909
13561
|
if (selected !== void 0)
|
|
12910
13562
|
return options.includes(selected) ? { value: selected, issue: null } : { value: null, issue: "invalid" };
|
|
12911
|
-
if (
|
|
12912
|
-
return { value:
|
|
13563
|
+
if (declaredDefault2 !== void 0 && options.includes(declaredDefault2))
|
|
13564
|
+
return { value: declaredDefault2, issue: null };
|
|
12913
13565
|
if (options.length === 1)
|
|
12914
13566
|
return { value: options[0], issue: null };
|
|
12915
13567
|
return { value: null, issue: options.length === 0 ? "unavailable" : "required" };
|
|
@@ -12920,7 +13572,6 @@ function isSecret(declaration) {
|
|
|
12920
13572
|
function seedConfiguration(configuration) {
|
|
12921
13573
|
const properties = configuration?.properties ?? {};
|
|
12922
13574
|
const required = new Set(configuration?.required ?? []);
|
|
12923
|
-
const values = {};
|
|
12924
13575
|
const open = [];
|
|
12925
13576
|
const requiredSecrets = [];
|
|
12926
13577
|
const groups = Object.entries(configuration?.dependentRequired ?? {}).map(([trigger, dependents]) => {
|
|
@@ -12931,22 +13582,81 @@ function seedConfiguration(configuration) {
|
|
|
12931
13582
|
secrets: members.filter((name) => isSecret(properties[name] ?? {}))
|
|
12932
13583
|
};
|
|
12933
13584
|
}).sort((a, b) => a.trigger.localeCompare(b.trigger));
|
|
13585
|
+
const values = seedProperties(properties, required, [], open, requiredSecrets);
|
|
13586
|
+
return { values, open, requiredSecrets, groups };
|
|
13587
|
+
}
|
|
13588
|
+
function seedProperties(properties, required, ancestors, open, requiredSecrets) {
|
|
13589
|
+
const values = {};
|
|
12934
13590
|
for (const [name, declaration] of Object.entries(properties)) {
|
|
12935
|
-
if (isSecret(declaration)) {
|
|
13591
|
+
if (requiredSecrets !== null && isSecret(declaration)) {
|
|
12936
13592
|
if (required.has(name))
|
|
12937
13593
|
requiredSecrets.push(name);
|
|
12938
13594
|
continue;
|
|
12939
13595
|
}
|
|
13596
|
+
const children = containerChildren2(declaration);
|
|
13597
|
+
if (children !== null) {
|
|
13598
|
+
if (!required.has(name))
|
|
13599
|
+
continue;
|
|
13600
|
+
const childRequired = new Set(children.required);
|
|
13601
|
+
const inner = [...ancestors, name];
|
|
13602
|
+
if (children.kind === "object") {
|
|
13603
|
+
values[name] = seedProperties(children.properties, childRequired, inner, open, null);
|
|
13604
|
+
continue;
|
|
13605
|
+
}
|
|
13606
|
+
const count = children.minItems ?? 0;
|
|
13607
|
+
values[name] = Array.from({ length: count }, () => seedProperties(children.properties, childRequired, inner, open, null));
|
|
13608
|
+
if (count > 1)
|
|
13609
|
+
dedupeOpen(open);
|
|
13610
|
+
continue;
|
|
13611
|
+
}
|
|
12940
13612
|
if (declaration.default !== void 0) {
|
|
12941
13613
|
values[name] = declaration.default;
|
|
12942
13614
|
continue;
|
|
12943
13615
|
}
|
|
12944
13616
|
if (required.has(name)) {
|
|
12945
13617
|
values[name] = "";
|
|
12946
|
-
|
|
13618
|
+
const path = configurationPath(...ancestors, name);
|
|
13619
|
+
open.push({
|
|
13620
|
+
name: path ?? name,
|
|
13621
|
+
label: path === null ? name : printableConfigurationPath(path),
|
|
13622
|
+
type: declaration.type ?? null
|
|
13623
|
+
});
|
|
12947
13624
|
}
|
|
12948
13625
|
}
|
|
12949
|
-
return
|
|
13626
|
+
return values;
|
|
13627
|
+
}
|
|
13628
|
+
function containerChildren2(declaration) {
|
|
13629
|
+
const node = declaration;
|
|
13630
|
+
if (node.type === "object" && node.properties !== void 0) {
|
|
13631
|
+
return {
|
|
13632
|
+
kind: "object",
|
|
13633
|
+
properties: node.properties,
|
|
13634
|
+
required: node.required ?? []
|
|
13635
|
+
};
|
|
13636
|
+
}
|
|
13637
|
+
if (node.type === "array" && node.items !== void 0) {
|
|
13638
|
+
const items = node.items;
|
|
13639
|
+
if (items.type !== "object" || items.properties === void 0)
|
|
13640
|
+
return null;
|
|
13641
|
+
return {
|
|
13642
|
+
kind: "array",
|
|
13643
|
+
properties: items.properties,
|
|
13644
|
+
required: items.required ?? [],
|
|
13645
|
+
...typeof node.minItems === "number" ? { minItems: node.minItems } : {}
|
|
13646
|
+
};
|
|
13647
|
+
}
|
|
13648
|
+
return null;
|
|
13649
|
+
}
|
|
13650
|
+
function dedupeOpen(open) {
|
|
13651
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13652
|
+
const unique = open.filter((entry) => {
|
|
13653
|
+
if (seen.has(entry.name))
|
|
13654
|
+
return false;
|
|
13655
|
+
seen.add(entry.name);
|
|
13656
|
+
return true;
|
|
13657
|
+
});
|
|
13658
|
+
open.length = 0;
|
|
13659
|
+
open.push(...unique);
|
|
12950
13660
|
}
|
|
12951
13661
|
function productInstanceExample(input) {
|
|
12952
13662
|
return {
|
|
@@ -13059,13 +13769,32 @@ var OperationStatusSchema = external_exports.enum([
|
|
|
13059
13769
|
|
|
13060
13770
|
// ../product-contracts/dist/api-version.js
|
|
13061
13771
|
var PRODUCT_API_VERSION = "products.vardeflyt.no/v1";
|
|
13772
|
+
var PRODUCT_API_VERSION_V2 = "products.vardeflyt.no/v2";
|
|
13773
|
+
var PARSEABLE_PRODUCT_API_VERSIONS = /* @__PURE__ */ new Set([
|
|
13774
|
+
PRODUCT_API_VERSION,
|
|
13775
|
+
PRODUCT_API_VERSION_V2
|
|
13776
|
+
]);
|
|
13777
|
+
function supportedList() {
|
|
13778
|
+
return [...PARSEABLE_PRODUCT_API_VERSIONS].map((value) => `"${value}"`).join(" or ");
|
|
13779
|
+
}
|
|
13780
|
+
function unsupportedProductApiVersionMessage() {
|
|
13781
|
+
return `apiVersion must be ${supportedList()}. An unrecognized contract format is refused rather than ignored.`;
|
|
13782
|
+
}
|
|
13062
13783
|
var PRODUCT_DEFINITION_KIND = "ProductDefinition";
|
|
13063
13784
|
var DEPLOYMENT_BLUEPRINT_KIND = "DeploymentBlueprint";
|
|
13064
13785
|
var ProductApiVersionSchema = external_exports.literal(PRODUCT_API_VERSION, {
|
|
13065
13786
|
errorMap: () => ({
|
|
13066
|
-
message: `apiVersion must be
|
|
13787
|
+
message: `apiVersion must be ${supportedList()}. An unrecognized contract format is refused rather than ignored.`
|
|
13067
13788
|
})
|
|
13068
13789
|
});
|
|
13790
|
+
var ProductApiVersionV2Schema = external_exports.literal(PRODUCT_API_VERSION_V2, {
|
|
13791
|
+
errorMap: () => ({
|
|
13792
|
+
message: `apiVersion must be ${supportedList()}. An unrecognized contract format is refused rather than ignored.`
|
|
13793
|
+
})
|
|
13794
|
+
});
|
|
13795
|
+
var ProductApiVersionAnySchema = external_exports.union([ProductApiVersionSchema, ProductApiVersionV2Schema], {
|
|
13796
|
+
errorMap: () => ({ message: unsupportedProductApiVersionMessage() })
|
|
13797
|
+
}).describe("The Product contract format this document is written against.");
|
|
13069
13798
|
var ResourceApiVersionSchema = external_exports.literal(RESOURCE_API_VERSION, {
|
|
13070
13799
|
errorMap: () => ({
|
|
13071
13800
|
message: `apiVersion must be "${RESOURCE_API_VERSION}". An unrecognized contract format is refused rather than ignored.`
|
|
@@ -13442,6 +14171,18 @@ var ProductConditionSchema = external_exports.object({
|
|
|
13442
14171
|
*/
|
|
13443
14172
|
description: external_exports.string().min(10).max(300)
|
|
13444
14173
|
}).strict();
|
|
14174
|
+
var RequiredWhenSchema = external_exports.object({
|
|
14175
|
+
/** A declared, non-secret customer-configuration property. */
|
|
14176
|
+
property: external_exports.string().regex(CONFIGURATION_PROPERTY_NAME_REGEX, "Must name a declared customer-configuration property."),
|
|
14177
|
+
/** The values that make this dependency required. Non-empty. */
|
|
14178
|
+
anyOf: external_exports.array(external_exports.string().min(1).max(80)).min(1).max(40)
|
|
14179
|
+
}).strict();
|
|
14180
|
+
var RequiredWhenV2Schema = external_exports.object({
|
|
14181
|
+
path: external_exports.string().refine((raw) => parseConfigurationPath(raw) !== null, {
|
|
14182
|
+
message: 'A configuration path is a root property name, or an RFC 6901 pointer such as "/assistant/model".'
|
|
14183
|
+
}),
|
|
14184
|
+
anyOf: external_exports.array(external_exports.string().min(1).max(80)).min(1).max(40)
|
|
14185
|
+
}).strict();
|
|
13445
14186
|
var ProductDependencySchema = external_exports.object({
|
|
13446
14187
|
/**
|
|
13447
14188
|
* OPTIONAL ONLY WHEN `interface` IS PRESENT, enforced below.
|
|
@@ -13556,13 +14297,11 @@ var ProductDependencySchema = external_exports.object({
|
|
|
13556
14297
|
* `.optional()`, never `.default()` — see the Blueprint's banner on
|
|
13557
14298
|
* `runtime`. Every dependency published to date carries none.
|
|
13558
14299
|
*/
|
|
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()
|
|
14300
|
+
requiredWhen: RequiredWhenSchema.optional()
|
|
13565
14301
|
}).strict();
|
|
14302
|
+
var ProductDependencyV2Schema = ProductDependencySchema.extend({
|
|
14303
|
+
requiredWhen: RequiredWhenV2Schema.optional()
|
|
14304
|
+
});
|
|
13566
14305
|
var ServiceInterfaceProvideSchema = external_exports.object({
|
|
13567
14306
|
key: ServiceBindingKeySchema,
|
|
13568
14307
|
interfaceId: ServiceInterfaceIdSchema,
|
|
@@ -13699,7 +14438,14 @@ var ProductDefinitionObjectSchema = external_exports.object({
|
|
|
13699
14438
|
*/
|
|
13700
14439
|
blueprint: external_exports.object({ version: ContractVersionSchema }).strict()
|
|
13701
14440
|
}).strict();
|
|
13702
|
-
var ProductDefinitionSchema = ProductDefinitionObjectSchema.superRefine(
|
|
14441
|
+
var ProductDefinitionSchema = ProductDefinitionObjectSchema.superRefine(checkProductDefinition);
|
|
14442
|
+
var ProductDefinitionV2ObjectSchema = ProductDefinitionObjectSchema.extend({
|
|
14443
|
+
apiVersion: ProductApiVersionV2Schema,
|
|
14444
|
+
configuration: CustomerConfigurationV2Schema,
|
|
14445
|
+
dependencies: external_exports.array(ProductDependencyV2Schema).max(8)
|
|
14446
|
+
});
|
|
14447
|
+
var ProductDefinitionV2Schema = ProductDefinitionV2ObjectSchema.superRefine(checkProductDefinition);
|
|
14448
|
+
function checkProductDefinition(definition, ctx) {
|
|
13703
14449
|
const profileIds = definition.profiles.map((profile) => profile.id);
|
|
13704
14450
|
const duplicateProfiles = profileIds.filter((id, i) => profileIds.indexOf(id) !== i);
|
|
13705
14451
|
if (duplicateProfiles.length > 0) {
|
|
@@ -13821,42 +14567,55 @@ var ProductDefinitionSchema = ProductDefinitionObjectSchema.superRefine((definit
|
|
|
13821
14567
|
message: "Repeated values in `anyOf`."
|
|
13822
14568
|
});
|
|
13823
14569
|
}
|
|
13824
|
-
const
|
|
13825
|
-
|
|
14570
|
+
const named = "path" in condition ? condition.path : condition.property;
|
|
14571
|
+
const member = "path" in condition ? "path" : "property";
|
|
14572
|
+
const parsed = parseConfigurationPath(named);
|
|
14573
|
+
const leaf = parsed === null ? null : leafAt(definition.configuration, parsed);
|
|
14574
|
+
if (leaf === null) {
|
|
14575
|
+
const isGroup = parsed !== null && declaresPath(definition.configuration, parsed);
|
|
14576
|
+
ctx.addIssue({
|
|
14577
|
+
code: external_exports.ZodIssueCode.custom,
|
|
14578
|
+
path: [...at, member],
|
|
14579
|
+
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.`
|
|
14580
|
+
});
|
|
14581
|
+
return;
|
|
14582
|
+
}
|
|
14583
|
+
if (underList(leaf)) {
|
|
13826
14584
|
ctx.addIssue({
|
|
13827
14585
|
code: external_exports.ZodIssueCode.custom,
|
|
13828
|
-
path: [...at,
|
|
13829
|
-
message: `"${
|
|
14586
|
+
path: [...at, member],
|
|
14587
|
+
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
14588
|
});
|
|
13831
14589
|
return;
|
|
13832
14590
|
}
|
|
14591
|
+
const property = leaf.property;
|
|
13833
14592
|
if (property.type !== "string") {
|
|
13834
14593
|
ctx.addIssue({
|
|
13835
14594
|
code: external_exports.ZodIssueCode.custom,
|
|
13836
|
-
path: [...at,
|
|
13837
|
-
message: `"${
|
|
14595
|
+
path: [...at, member],
|
|
14596
|
+
message: `"${named}" is a ${property.type} setting; a condition compares string values.`
|
|
13838
14597
|
});
|
|
13839
14598
|
return;
|
|
13840
14599
|
}
|
|
13841
|
-
if (property
|
|
14600
|
+
if (isSecretProperty(property)) {
|
|
13842
14601
|
ctx.addIssue({
|
|
13843
14602
|
code: external_exports.ZodIssueCode.custom,
|
|
13844
|
-
path: [...at,
|
|
13845
|
-
message: `"${
|
|
14603
|
+
path: [...at, member],
|
|
14604
|
+
message: `"${named}" is a secret. The platform never reads a secret's value, so a condition on one could never be evaluated.`
|
|
13846
14605
|
});
|
|
13847
14606
|
return;
|
|
13848
14607
|
}
|
|
13849
14608
|
const single = withoutCrossFieldRules({
|
|
13850
14609
|
...definition.configuration,
|
|
13851
|
-
properties: { [
|
|
13852
|
-
required: [
|
|
14610
|
+
properties: { [leaf.name]: property },
|
|
14611
|
+
required: [leaf.name]
|
|
13853
14612
|
});
|
|
13854
|
-
const outside = condition.anyOf.filter((value) => !validateSubmittedConfiguration(single, { [
|
|
14613
|
+
const outside = condition.anyOf.filter((value) => !validateSubmittedConfiguration(single, { [leaf.name]: value }).ok);
|
|
13855
14614
|
if (outside.length > 0) {
|
|
13856
14615
|
ctx.addIssue({
|
|
13857
14616
|
code: external_exports.ZodIssueCode.custom,
|
|
13858
14617
|
path: [...at, "anyOf"],
|
|
13859
|
-
message: `"${
|
|
14618
|
+
message: `"${named}" never accepts ${outside.map((v) => `"${v}"`).join(", ")}, so this condition could never make the dependency required.`
|
|
13860
14619
|
});
|
|
13861
14620
|
}
|
|
13862
14621
|
});
|
|
@@ -13970,7 +14729,7 @@ var ProductDefinitionSchema = ProductDefinitionObjectSchema.superRefine((definit
|
|
|
13970
14729
|
message: 'dataResidency "global" contradicts externalProcessing false \u2014 data cannot be global without leaving the tenant boundary.'
|
|
13971
14730
|
});
|
|
13972
14731
|
}
|
|
13973
|
-
}
|
|
14732
|
+
}
|
|
13974
14733
|
|
|
13975
14734
|
// ../product-contracts/dist/announcements.js
|
|
13976
14735
|
var ANNOUNCED_PRODUCTS = Object.freeze([
|
|
@@ -14160,108 +14919,166 @@ var ComponentIngressSchema = external_exports.discriminatedUnion("exposure", [
|
|
|
14160
14919
|
authentication: external_exports.enum(["signed-request", "mtls"])
|
|
14161
14920
|
}).strict()
|
|
14162
14921
|
]);
|
|
14922
|
+
var LiteralEnvBindingSchema = external_exports.object({
|
|
14923
|
+
source: external_exports.literal("literal"),
|
|
14924
|
+
name: EnvVarNameSchema,
|
|
14925
|
+
value: external_exports.string().max(512)
|
|
14926
|
+
}).strict();
|
|
14927
|
+
var InstanceEnvBindingSchema = external_exports.object({
|
|
14928
|
+
source: external_exports.literal("instance"),
|
|
14929
|
+
name: EnvVarNameSchema,
|
|
14930
|
+
/** Closed set: the Control Plane knows these without Product knowledge. */
|
|
14931
|
+
field: external_exports.enum([
|
|
14932
|
+
"tenantKey",
|
|
14933
|
+
"tenantId",
|
|
14934
|
+
"projectId",
|
|
14935
|
+
"productInstanceId",
|
|
14936
|
+
"instanceKey",
|
|
14937
|
+
"productId",
|
|
14938
|
+
"productVersion",
|
|
14939
|
+
"profile",
|
|
14940
|
+
"region",
|
|
14941
|
+
"environment"
|
|
14942
|
+
])
|
|
14943
|
+
}).strict();
|
|
14944
|
+
var PlatformEnvBindingSchema = external_exports.object({
|
|
14945
|
+
source: external_exports.literal("platform"),
|
|
14946
|
+
name: EnvVarNameSchema,
|
|
14947
|
+
key: external_exports.enum(["controlPlaneUrl", "observabilityEndpoint", "logLevel", "serviceVersion"])
|
|
14948
|
+
}).strict();
|
|
14949
|
+
var ComponentEndpointEnvBindingSchema = external_exports.object({
|
|
14950
|
+
source: external_exports.literal("component-endpoint"),
|
|
14951
|
+
name: EnvVarNameSchema,
|
|
14952
|
+
/** Resolved to the sibling component's private URL at reconcile time. */
|
|
14953
|
+
componentId: ComponentIdSchema
|
|
14954
|
+
}).strict();
|
|
14955
|
+
var ComponentPublicUrlEnvBindingSchema = external_exports.object({
|
|
14956
|
+
/**
|
|
14957
|
+
* The CUSTOMER-FACING address of a PUBLIC component — the URL a browser
|
|
14958
|
+
* opens, not the in-network one a sibling calls.
|
|
14959
|
+
*
|
|
14960
|
+
* WHY THE PLATFORM HAS TO SUPPLY IT. The address is assigned during
|
|
14961
|
+
* deployment, so nobody knows it earlier: not the publisher, who writes
|
|
14962
|
+
* the contract months before, and not the customer, who would otherwise
|
|
14963
|
+
* be asked to type an address that does not exist yet. A console that
|
|
14964
|
+
* needs its own address — to build an OAuth redirect URI, to put an
|
|
14965
|
+
* absolute link in an email — had no way to learn it, and asking the
|
|
14966
|
+
* customer produced exactly the failure you would expect: an empty
|
|
14967
|
+
* setting and a console nobody can sign in to.
|
|
14968
|
+
*
|
|
14969
|
+
* It is deliberately NOT derivable from the request. A server behind a
|
|
14970
|
+
* proxy infers its bind address, which looks right in development and is
|
|
14971
|
+
* wrong in production; a forwarded Host header is attacker-controlled.
|
|
14972
|
+
* The platform knows the answer, so the platform states it.
|
|
14973
|
+
*
|
|
14974
|
+
* `componentId` may name this component or another, but it must be a
|
|
14975
|
+
* PUBLIC one: `validateProductContracts` refuses a private target, the
|
|
14976
|
+
* same rule `outputs` already carries, because a private endpoint is not
|
|
14977
|
+
* an address to hand out.
|
|
14978
|
+
*/
|
|
14979
|
+
source: external_exports.literal("component-public-url"),
|
|
14980
|
+
name: EnvVarNameSchema,
|
|
14981
|
+
componentId: ComponentIdSchema
|
|
14982
|
+
}).strict();
|
|
14983
|
+
var ServiceBindingAttributeEnvBindingSchema = external_exports.object({
|
|
14984
|
+
/**
|
|
14985
|
+
* A NON-SECRET value from a service binding to ANOTHER Product.
|
|
14986
|
+
*
|
|
14987
|
+
* THE ONLY SOURCE THAT LEAVES THIS PRODUCT INSTANCE. Every other member of
|
|
14988
|
+
* this union resolves inside one deployment: a literal, a fact about this
|
|
14989
|
+
* instance, a sibling component's address, a setting this customer typed.
|
|
14990
|
+
* This one is answered by a different Product Instance, possibly in a
|
|
14991
|
+
* different logical Project, which is why it is the only source whose
|
|
14992
|
+
* value can be absent for a reason that is nobody's mistake.
|
|
14993
|
+
*
|
|
14994
|
+
* ABSENT WHILE THE BINDING IS PENDING, and absent rather than empty. The
|
|
14995
|
+
* variable is left out of the container entirely until the provider
|
|
14996
|
+
* completes the binding, so a Product can tell "not yet" from "set to
|
|
14997
|
+
* nothing" — the same rule `configuration` already follows. Read
|
|
14998
|
+
* `VFAC_SERVICE_BINDING_<KEY>_STATUS`, which the platform injects for
|
|
14999
|
+
* every declared binding, rather than inferring readiness from absence.
|
|
15000
|
+
*
|
|
15001
|
+
* CREDENTIALS DO NOT COME THIS WAY. `field` must name a field the
|
|
15002
|
+
* interface classifies as an attribute; a secret field bound here is
|
|
15003
|
+
* refused by `validateProductContracts()`, and the credential-shaped-name
|
|
15004
|
+
* rule below refuses the variable name independently.
|
|
15005
|
+
*/
|
|
15006
|
+
source: external_exports.literal("service-binding-attribute"),
|
|
15007
|
+
name: EnvVarNameSchema,
|
|
15008
|
+
/** The `serviceBindings[].key` this value comes from. */
|
|
15009
|
+
binding: ServiceBindingKeySchema,
|
|
15010
|
+
/** The interface field, e.g. `issuerUrl`. Checked against the registry. */
|
|
15011
|
+
field: external_exports.string().regex(/^[a-z][a-zA-Z0-9]{1,47}$/)
|
|
15012
|
+
}).strict();
|
|
15013
|
+
var ConfigurationEnvBindingSchema = external_exports.object({
|
|
15014
|
+
source: external_exports.literal("configuration"),
|
|
15015
|
+
name: EnvVarNameSchema,
|
|
15016
|
+
/**
|
|
15017
|
+
* A NON-SECRET customer setting from the Product Definition.
|
|
15018
|
+
* `validateProductContracts()` rejects a reference to an `x-secret`
|
|
15019
|
+
* property — those travel through `secrets[]` and Secret Manager, never
|
|
15020
|
+
* through plain environment wiring.
|
|
15021
|
+
*/
|
|
15022
|
+
property: external_exports.string().regex(/^[a-z][a-zA-Z0-9]{1,47}$/)
|
|
15023
|
+
}).strict();
|
|
14163
15024
|
var EnvBindingSchema = external_exports.discriminatedUnion("source", [
|
|
15025
|
+
LiteralEnvBindingSchema,
|
|
15026
|
+
InstanceEnvBindingSchema,
|
|
15027
|
+
PlatformEnvBindingSchema,
|
|
15028
|
+
ComponentEndpointEnvBindingSchema,
|
|
15029
|
+
ComponentPublicUrlEnvBindingSchema,
|
|
15030
|
+
ServiceBindingAttributeEnvBindingSchema,
|
|
15031
|
+
ConfigurationEnvBindingSchema
|
|
15032
|
+
]);
|
|
15033
|
+
var ConfigurationBindingPathSchema = external_exports.string().refine((raw) => parseConfigurationPath(raw) !== null, {
|
|
15034
|
+
message: 'A configuration path is a root property name, or an RFC 6901 pointer such as "/assistant/model".'
|
|
15035
|
+
}).refine((raw) => !/\/\d+(\/|$)/.test(raw), {
|
|
15036
|
+
message: 'A Blueprint binds a DECLARED setting, so a path may not carry a list index. Bind the list with "configuration-json".'
|
|
15037
|
+
});
|
|
15038
|
+
var EnvBindingV2Schema = external_exports.discriminatedUnion("source", [
|
|
15039
|
+
LiteralEnvBindingSchema,
|
|
15040
|
+
InstanceEnvBindingSchema,
|
|
15041
|
+
PlatformEnvBindingSchema,
|
|
15042
|
+
ComponentEndpointEnvBindingSchema,
|
|
15043
|
+
ComponentPublicUrlEnvBindingSchema,
|
|
15044
|
+
ServiceBindingAttributeEnvBindingSchema,
|
|
14164
15045
|
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"),
|
|
15046
|
+
source: external_exports.literal("configuration"),
|
|
14193
15047
|
name: EnvVarNameSchema,
|
|
14194
|
-
/** Resolved to the sibling component's private URL at reconcile time. */
|
|
14195
|
-
componentId: ComponentIdSchema
|
|
14196
|
-
}).strict(),
|
|
14197
|
-
external_exports.object({
|
|
14198
15048
|
/**
|
|
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.
|
|
15049
|
+
* A NON-SECRET customer setting, named by its canonical path.
|
|
14210
15050
|
*
|
|
14211
|
-
*
|
|
14212
|
-
*
|
|
14213
|
-
*
|
|
14214
|
-
*
|
|
14215
|
-
*
|
|
14216
|
-
* `componentId` may name this component or another, but it must be a
|
|
14217
|
-
* PUBLIC one: `validateProductContracts` refuses a private target, the
|
|
14218
|
-
* same rule `outputs` already carries, because a private endpoint is not
|
|
14219
|
-
* an address to hand out.
|
|
15051
|
+
* `validateProductContracts` refuses a path that names no leaf, a path
|
|
15052
|
+
* that names a GROUP — a group has no scalar rendering, and
|
|
15053
|
+
* `configuration-json` is how one is carried — and any `x-secret`
|
|
15054
|
+
* property, which travels through `secrets[]` and never through plain
|
|
15055
|
+
* environment wiring.
|
|
14220
15056
|
*/
|
|
14221
|
-
|
|
14222
|
-
name: EnvVarNameSchema,
|
|
14223
|
-
componentId: ComponentIdSchema
|
|
15057
|
+
path: ConfigurationBindingPathSchema
|
|
14224
15058
|
}).strict(),
|
|
14225
15059
|
external_exports.object({
|
|
15060
|
+
source: external_exports.literal("configuration-json"),
|
|
15061
|
+
name: EnvVarNameSchema,
|
|
14226
15062
|
/**
|
|
14227
|
-
*
|
|
15063
|
+
* THE WHOLE VALIDATED CONFIGURATION, OR ONE SUBTREE OF IT, AS JSON.
|
|
14228
15064
|
*
|
|
14229
|
-
*
|
|
14230
|
-
*
|
|
14231
|
-
*
|
|
14232
|
-
*
|
|
14233
|
-
*
|
|
14234
|
-
*
|
|
15065
|
+
* WHY THIS EXISTS. A component may carry at most forty environment
|
|
15066
|
+
* bindings, and a nested Product spends one per leaf — so the format that
|
|
15067
|
+
* lets a Product have structure would immediately run out of room to
|
|
15068
|
+
* deliver it. This binds a whole document instead, and the Product's own
|
|
15069
|
+
* runtime translates it into whatever shape it wants. The Control Plane
|
|
15070
|
+
* learns nothing about that shape, which is the point.
|
|
14235
15071
|
*
|
|
14236
|
-
*
|
|
14237
|
-
*
|
|
14238
|
-
*
|
|
14239
|
-
*
|
|
14240
|
-
*
|
|
14241
|
-
*
|
|
15072
|
+
* WHAT IT CARRIES: validated, non-secret configuration with resolved
|
|
15073
|
+
* ORDINARY resource references materialised in place. Never a secret
|
|
15074
|
+
* value — secrets are root-only and travel through `secrets[]`, and a
|
|
15075
|
+
* subtree cannot contain one. Serialised with `canonicalJson`, so the same
|
|
15076
|
+
* logical configuration is the same bytes and the environment fingerprint
|
|
15077
|
+
* does not move on key order alone.
|
|
14242
15078
|
*
|
|
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.
|
|
15079
|
+
* Absent `path` means the whole document.
|
|
14263
15080
|
*/
|
|
14264
|
-
|
|
15081
|
+
path: ConfigurationBindingPathSchema.optional()
|
|
14265
15082
|
}).strict()
|
|
14266
15083
|
]);
|
|
14267
15084
|
var MAX_BOOTSTRAP_SCRIPT_LENGTH = 32768;
|
|
@@ -14473,11 +15290,12 @@ var ComponentDependencySchema = external_exports.object({
|
|
|
14473
15290
|
minVersion: ContractVersionSchema.optional(),
|
|
14474
15291
|
maxVersion: ContractVersionSchema.optional()
|
|
14475
15292
|
}).strict();
|
|
15293
|
+
var MAX_COMPONENT_ENV_BINDINGS = 40;
|
|
14476
15294
|
var componentCommonShape = {
|
|
14477
15295
|
id: ComponentIdSchema.describe("Scoped by its Product; does not repeat the Product ID (\xA78)."),
|
|
14478
15296
|
kind: ComponentKindSchema,
|
|
14479
15297
|
description: external_exports.string().min(10).max(300),
|
|
14480
|
-
env: external_exports.array(EnvBindingSchema).max(
|
|
15298
|
+
env: external_exports.array(EnvBindingSchema).max(MAX_COMPONENT_ENV_BINDINGS),
|
|
14481
15299
|
dependsOn: external_exports.array(ComponentDependencySchema).max(8)
|
|
14482
15300
|
};
|
|
14483
15301
|
var ServerlessContainerComponentSchema = external_exports.object({
|
|
@@ -14529,6 +15347,16 @@ var RuntimeComponentSchema = external_exports.discriminatedUnion("runtime", [
|
|
|
14529
15347
|
ServerlessContainerComponentSchema,
|
|
14530
15348
|
VirtualMachineComponentSchema
|
|
14531
15349
|
]);
|
|
15350
|
+
var ServerlessContainerComponentV2Schema = ServerlessContainerComponentSchema.extend({
|
|
15351
|
+
env: external_exports.array(EnvBindingV2Schema).max(MAX_COMPONENT_ENV_BINDINGS)
|
|
15352
|
+
});
|
|
15353
|
+
var VirtualMachineComponentV2Schema = VirtualMachineComponentSchema.extend({
|
|
15354
|
+
env: external_exports.array(EnvBindingV2Schema).max(MAX_COMPONENT_ENV_BINDINGS)
|
|
15355
|
+
});
|
|
15356
|
+
var RuntimeComponentV2Schema = external_exports.discriminatedUnion("runtime", [
|
|
15357
|
+
ServerlessContainerComponentV2Schema,
|
|
15358
|
+
VirtualMachineComponentV2Schema
|
|
15359
|
+
]);
|
|
14532
15360
|
function isVirtualMachineComponent(component) {
|
|
14533
15361
|
return component.runtime === "virtual-machine";
|
|
14534
15362
|
}
|
|
@@ -14777,7 +15605,47 @@ var BlueprintLifecycleSchema = external_exports.object({
|
|
|
14777
15605
|
* the service-interface surface is unchanged. Nothing published to date
|
|
14778
15606
|
* regresses, and a release cannot strand an instance by forgetting it.
|
|
14779
15607
|
*/
|
|
14780
|
-
directFromVersions: external_exports.array(ContractVersionSchema).max(20).optional()
|
|
15608
|
+
directFromVersions: external_exports.array(ContractVersionSchema).max(20).optional(),
|
|
15609
|
+
/**
|
|
15610
|
+
* How a stored configuration is carried across a release that MOVED a
|
|
15611
|
+
* setting.
|
|
15612
|
+
*
|
|
15613
|
+
* THE CASE THIS EXISTS FOR is a flat Product taking on structure:
|
|
15614
|
+
* `assistantName` becomes `/assistant/name`. Nothing else on this
|
|
15615
|
+
* platform can express that. Without it the target release simply does
|
|
15616
|
+
* not declare `assistantName`, so the upgrade drops the customer's value
|
|
15617
|
+
* and then refuses the deploy for a missing required setting — and the
|
|
15618
|
+
* customer's answer is gone either way.
|
|
15619
|
+
*
|
|
15620
|
+
* `move` AND NOTHING ELSE. A migration the platform cannot fully
|
|
15621
|
+
* evaluate is one it cannot apply safely, and every other operation a
|
|
15622
|
+
* publisher might want — rename a value, split one setting into two,
|
|
15623
|
+
* compute a default — needs the Product's own knowledge of what those
|
|
15624
|
+
* values MEAN. Moving a value is the one thing the platform can do
|
|
15625
|
+
* correctly without knowing anything about it.
|
|
15626
|
+
*
|
|
15627
|
+
* APPLIED AT CUTOVER, in the transaction that writes the new
|
|
15628
|
+
* configuration, and to the REFERENCE ROWS as well as the stored
|
|
15629
|
+
* document — a Resource Reference is identified by the path it answers,
|
|
15630
|
+
* so a setting that moved takes its edge with it or the edge points at
|
|
15631
|
+
* nothing.
|
|
15632
|
+
*
|
|
15633
|
+
* AN ABSENT SOURCE IS A NO-OP, deliberately. A customer who never
|
|
15634
|
+
* answered an optional setting has nothing to carry, and inventing an
|
|
15635
|
+
* empty value for them would turn "not configured" into "configured
|
|
15636
|
+
* blank" — two states this platform keeps apart everywhere else.
|
|
15637
|
+
*
|
|
15638
|
+
* `.optional()`, never `.default([])`, for the reason
|
|
15639
|
+
* `directFromVersions` states one field above: a materialised key makes
|
|
15640
|
+
* a byte-identical republish `RELEASED_CONTRACT_MUTATED`.
|
|
15641
|
+
*/
|
|
15642
|
+
configurationMigrations: external_exports.array(external_exports.object({
|
|
15643
|
+
op: external_exports.literal("move"),
|
|
15644
|
+
/** Where the value is today, in the release being left. */
|
|
15645
|
+
from: ConfigurationBindingPathSchema,
|
|
15646
|
+
/** Where this release declares it. */
|
|
15647
|
+
to: ConfigurationBindingPathSchema
|
|
15648
|
+
}).strict()).max(40).optional()
|
|
14781
15649
|
}).strict(),
|
|
14782
15650
|
rollback: external_exports.object({
|
|
14783
15651
|
supported: external_exports.boolean(),
|
|
@@ -14903,7 +15771,14 @@ function isOidcClientServiceBinding(binding) {
|
|
|
14903
15771
|
}
|
|
14904
15772
|
var DeploymentBlueprintObjectSchema = external_exports.object({
|
|
14905
15773
|
/** The CONTRACT FORMAT version — not the Blueprint's. See api-version.ts. */
|
|
14906
|
-
|
|
15774
|
+
/**
|
|
15775
|
+
* The SHARED base carries either literal; each format pins its own below.
|
|
15776
|
+
*
|
|
15777
|
+
* Nothing parses this object schema directly — `DeploymentBlueprintV1Schema`
|
|
15778
|
+
* and `…V2Schema` extend it — so the permissive literal here is never what a
|
|
15779
|
+
* document is held to, and never what an artifact publishes.
|
|
15780
|
+
*/
|
|
15781
|
+
apiVersion: ProductApiVersionAnySchema,
|
|
14907
15782
|
kind: kindSchema(DEPLOYMENT_BLUEPRINT_KIND),
|
|
14908
15783
|
productId: ProductIdSchema,
|
|
14909
15784
|
/** This Blueprint's own version. The Definition pins it exactly. */
|
|
@@ -14971,7 +15846,17 @@ var DeploymentBlueprintObjectSchema = external_exports.object({
|
|
|
14971
15846
|
outputs: external_exports.array(BlueprintOutputSchema).min(1).max(12),
|
|
14972
15847
|
lifecycle: BlueprintLifecycleSchema
|
|
14973
15848
|
}).strict();
|
|
14974
|
-
var
|
|
15849
|
+
var DeploymentBlueprintV1ObjectSchema = DeploymentBlueprintObjectSchema.extend({
|
|
15850
|
+
apiVersion: ProductApiVersionSchema
|
|
15851
|
+
});
|
|
15852
|
+
var DeploymentBlueprintV2ObjectSchema = DeploymentBlueprintObjectSchema.extend({
|
|
15853
|
+
apiVersion: ProductApiVersionV2Schema,
|
|
15854
|
+
components: external_exports.array(RuntimeComponentV2Schema).min(1).max(MAX_RUNTIME_COMPONENTS)
|
|
15855
|
+
});
|
|
15856
|
+
var DeploymentBlueprintV1Schema = DeploymentBlueprintV1ObjectSchema.superRefine(checkDeploymentBlueprint);
|
|
15857
|
+
var DeploymentBlueprintV2Schema = DeploymentBlueprintV2ObjectSchema.superRefine(checkDeploymentBlueprint);
|
|
15858
|
+
var DeploymentBlueprintSchema = DeploymentBlueprintV1Schema;
|
|
15859
|
+
function checkDeploymentBlueprint(blueprint, ctx) {
|
|
14975
15860
|
const componentIds = blueprint.components.map((component) => component.id);
|
|
14976
15861
|
const knownComponents = new Set(componentIds);
|
|
14977
15862
|
const publicComponents = new Set(blueprint.components.filter((component) => component.ingress.exposure === "public").map((component) => component.id));
|
|
@@ -15072,13 +15957,7 @@ var DeploymentBlueprintSchema = DeploymentBlueprintObjectSchema.superRefine((blu
|
|
|
15072
15957
|
});
|
|
15073
15958
|
const handoff = resource.bootstrap.productHandoff;
|
|
15074
15959
|
if (handoff !== void 0) {
|
|
15075
|
-
const handoffPath = [
|
|
15076
|
-
"dynamicResources",
|
|
15077
|
-
index,
|
|
15078
|
-
"bootstrap",
|
|
15079
|
-
"productHandoff",
|
|
15080
|
-
"componentId"
|
|
15081
|
-
];
|
|
15960
|
+
const handoffPath = ["dynamicResources", index, "bootstrap", "productHandoff", "componentId"];
|
|
15082
15961
|
const target = blueprint.components.find((component) => component.id === handoff.componentId);
|
|
15083
15962
|
if (target === void 0) {
|
|
15084
15963
|
ctx.addIssue({
|
|
@@ -15689,7 +16568,7 @@ var DeploymentBlueprintSchema = DeploymentBlueprintObjectSchema.superRefine((blu
|
|
|
15689
16568
|
});
|
|
15690
16569
|
}
|
|
15691
16570
|
}
|
|
15692
|
-
}
|
|
16571
|
+
}
|
|
15693
16572
|
|
|
15694
16573
|
// ../product-contracts/dist/deployability.js
|
|
15695
16574
|
var VIRTUAL_MACHINE_PROFILE_INTERFACE = {
|
|
@@ -15730,6 +16609,9 @@ function isTerminalAction(action) {
|
|
|
15730
16609
|
}
|
|
15731
16610
|
var ManifestActionSchema = external_exports.enum(MANIFEST_ACTIONS);
|
|
15732
16611
|
|
|
16612
|
+
// ../product-contracts/dist/contract-issue.js
|
|
16613
|
+
var MAX_SEGMENTS = MAX_CONFIGURATION_PATH_SEGMENTS + 2;
|
|
16614
|
+
|
|
15733
16615
|
// ../product-contracts/dist/resource-output-reference.js
|
|
15734
16616
|
var OUTPUT_KEY_RULE = "Output keys are camelCase.";
|
|
15735
16617
|
var ResourceOutputReferenceSchema = external_exports.object({
|
|
@@ -15896,7 +16778,33 @@ var ProductSubmissionObjectSchema = external_exports.object({
|
|
|
15896
16778
|
definition: ProductDefinitionSchema,
|
|
15897
16779
|
blueprint: DeploymentBlueprintSchema
|
|
15898
16780
|
}).strict();
|
|
15899
|
-
var
|
|
16781
|
+
var submissionShape = {
|
|
16782
|
+
kind: kindSchema(PRODUCT_SUBMISSION_KIND),
|
|
16783
|
+
submission: SubmissionEnvelopeSchema
|
|
16784
|
+
};
|
|
16785
|
+
var ProductSubmissionV1ObjectSchema = external_exports.object({
|
|
16786
|
+
apiVersion: ProductApiVersionSchema,
|
|
16787
|
+
...submissionShape,
|
|
16788
|
+
definition: ProductDefinitionSchema,
|
|
16789
|
+
blueprint: DeploymentBlueprintV1Schema
|
|
16790
|
+
}).strict();
|
|
16791
|
+
var ProductSubmissionV2ObjectSchema = external_exports.object({
|
|
16792
|
+
apiVersion: ProductApiVersionV2Schema,
|
|
16793
|
+
...submissionShape,
|
|
16794
|
+
definition: ProductDefinitionV2Schema,
|
|
16795
|
+
blueprint: DeploymentBlueprintV2Schema
|
|
16796
|
+
}).strict();
|
|
16797
|
+
var ProductSubmissionV1Schema = ProductSubmissionV1ObjectSchema.superRefine(checkProductSubmission);
|
|
16798
|
+
var ProductSubmissionV2Schema = ProductSubmissionV2ObjectSchema.superRefine(checkProductSubmission);
|
|
16799
|
+
var ProductSubmissionSchema = ProductSubmissionV1Schema;
|
|
16800
|
+
function checkProductSubmission(submission, ctx) {
|
|
16801
|
+
if (submission.definition.apiVersion !== submission.apiVersion) {
|
|
16802
|
+
ctx.addIssue({
|
|
16803
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16804
|
+
path: ["definition", "apiVersion"],
|
|
16805
|
+
message: `This submission is written against "${submission.apiVersion}" but its Product Definition declares "${submission.definition.apiVersion}". One submission is one contract format.`
|
|
16806
|
+
});
|
|
16807
|
+
}
|
|
15900
16808
|
if (submission.definition.id !== submission.submission.productId) {
|
|
15901
16809
|
ctx.addIssue({
|
|
15902
16810
|
code: external_exports.ZodIssueCode.custom,
|
|
@@ -15918,7 +16826,7 @@ var ProductSubmissionSchema = ProductSubmissionObjectSchema.superRefine((submiss
|
|
|
15918
16826
|
message: `The Product Definition is version "${submission.definition.version}" but the submission claims "${submission.submission.version}". They must be the same version.`
|
|
15919
16827
|
});
|
|
15920
16828
|
}
|
|
15921
|
-
}
|
|
16829
|
+
}
|
|
15922
16830
|
var PUBLISH_RULE_ANNEX = {
|
|
15923
16831
|
allOf: [
|
|
15924
16832
|
{
|
|
@@ -16371,12 +17279,12 @@ async function runDoctor(parsed) {
|
|
|
16371
17279
|
ok: false,
|
|
16372
17280
|
detail: "not set. Run `vfac context set --endpoint https://your-organization.cloud.vardeflyt.no`, or set VFAC_ENDPOINT."
|
|
16373
17281
|
});
|
|
16374
|
-
return
|
|
17282
|
+
return report2(checks, json);
|
|
16375
17283
|
}
|
|
16376
17284
|
const checked = validateEndpoint(resolved.value, resolved.source);
|
|
16377
17285
|
if (!checked.ok) {
|
|
16378
17286
|
checks.push({ name: "Endpoint", ok: false, detail: checked.message });
|
|
16379
|
-
return
|
|
17287
|
+
return report2(checks, json);
|
|
16380
17288
|
}
|
|
16381
17289
|
const endpoint = checked.endpoint;
|
|
16382
17290
|
checks.push({
|
|
@@ -16396,16 +17304,16 @@ async function runDoctor(parsed) {
|
|
|
16396
17304
|
const probe = await probeMachineApi({ endpoint });
|
|
16397
17305
|
if (!probe.ok) {
|
|
16398
17306
|
checks.push({ name: "Machine API", ok: false, detail: probe.message });
|
|
16399
|
-
return
|
|
17307
|
+
return report2(checks, json);
|
|
16400
17308
|
}
|
|
16401
17309
|
checks.push({ name: "Machine API", ok: true, detail: probe.apiVersion });
|
|
16402
17310
|
const compatible = compatibility(cliVersion(), probe.minimumCliVersion);
|
|
16403
17311
|
checks.push(compatible);
|
|
16404
|
-
if (!compatible.ok) return
|
|
17312
|
+
if (!compatible.ok) return report2(checks, json);
|
|
16405
17313
|
const signedIn = await signIn({ endpoint });
|
|
16406
17314
|
if (!signedIn.ok) {
|
|
16407
17315
|
checks.push({ name: "Context Gate", ok: false, detail: signedIn.message });
|
|
16408
|
-
return
|
|
17316
|
+
return report2(checks, json);
|
|
16409
17317
|
}
|
|
16410
17318
|
checks.push({
|
|
16411
17319
|
name: "Context Gate",
|
|
@@ -16426,7 +17334,7 @@ async function runDoctor(parsed) {
|
|
|
16426
17334
|
ok: false,
|
|
16427
17335
|
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
17336
|
});
|
|
16429
|
-
return
|
|
17337
|
+
return report2(checks, json);
|
|
16430
17338
|
}
|
|
16431
17339
|
const access = who.data.access;
|
|
16432
17340
|
const projects = access.projects.map((project) => project.projectId);
|
|
@@ -16486,7 +17394,7 @@ async function runDoctor(parsed) {
|
|
|
16486
17394
|
detail: "run `vfac guide` for the platform's own instructions, written for a machine"
|
|
16487
17395
|
});
|
|
16488
17396
|
checks.push(await updateAvailable(cliVersion()));
|
|
16489
|
-
return
|
|
17397
|
+
return report2(checks, json);
|
|
16490
17398
|
}
|
|
16491
17399
|
function compatibility(local, declared) {
|
|
16492
17400
|
const name = "Compatibility";
|
|
@@ -16566,7 +17474,7 @@ async function updateAvailable(local) {
|
|
|
16566
17474
|
facts
|
|
16567
17475
|
};
|
|
16568
17476
|
}
|
|
16569
|
-
function
|
|
17477
|
+
function report2(checks, json) {
|
|
16570
17478
|
const failed = checks.filter((check) => !check.ok);
|
|
16571
17479
|
if (json) {
|
|
16572
17480
|
process.stdout.write(`${JSON.stringify({ ok: failed.length === 0, checks })}
|
|
@@ -16942,16 +17850,14 @@ function renderProduct(product) {
|
|
|
16942
17850
|
(profile) => `${profile.id}${profile.default ? " (default)" : ""}`
|
|
16943
17851
|
);
|
|
16944
17852
|
lines.push(` profile ${profiles.join(", ") || "(none declared)"}`);
|
|
16945
|
-
const
|
|
16946
|
-
|
|
16947
|
-
if (required.length > 0) {
|
|
17853
|
+
const seed = seedConfiguration(product.configuration);
|
|
17854
|
+
if (seed.open.length > 0 || seed.requiredSecrets.length > 0) {
|
|
16948
17855
|
lines.push("", " Required configuration");
|
|
16949
|
-
for (const name of
|
|
16950
|
-
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
);
|
|
17856
|
+
for (const name of seed.requiredSecrets) {
|
|
17857
|
+
lines.push(` ${name} (secret \u2014 pass --secret ${name}=env:VAR)`);
|
|
17858
|
+
}
|
|
17859
|
+
for (const setting of seed.open) {
|
|
17860
|
+
lines.push(` ${setting.label} ${setting.type ?? ""}`.trimEnd());
|
|
16955
17861
|
}
|
|
16956
17862
|
}
|
|
16957
17863
|
const needed = (product.dependencies ?? []).filter((dependency) => dependency.required);
|
|
@@ -17224,7 +18130,7 @@ async function runManifestInit(parsed) {
|
|
|
17224
18130
|
}
|
|
17225
18131
|
for (const setting of seed.open) {
|
|
17226
18132
|
notes.push(
|
|
17227
|
-
`spec.configuration.${setting.
|
|
18133
|
+
`spec.configuration.${setting.label} \u2014 required${setting.type ? ` (${setting.type})` : ""}`
|
|
17228
18134
|
);
|
|
17229
18135
|
}
|
|
17230
18136
|
for (const group of seed.groups) {
|