yaml importer slopping it up

This commit is contained in:
legop3
2026-09-14 13:48:58 -04:00
parent 8ff3c39765
commit 881583ee0a
4 changed files with 95 additions and 16 deletions
@@ -2,7 +2,32 @@
// Purpose: Validates one YAML file deliberately uploaded during first-run setup and stores it in the configuration database.
// Scope: This is an explicit setup action only; startup and installation never search for or consume configuration files.
const yaml = require('js-yaml');
const { normalizeConfig, assertValidConfig } = require('./validation');
const { rootSchema, normalizeConfig, assertValidConfig } = require('./validation');
function keepCurrentSchemaFields(value, schema) {
/*
An uploaded file is only a convenient seed for the current configuration;
it is not a second schema or a historical migration framework. Legacy YAML
was permissive, so real installations naturally contain keys left behind
by removed features. At object boundaries, copy only properties that exist
in today's schema and recursively apply the same rule to nested objects and
array items. Known fields retain their original values and are validated
normally afterward, so this cannot hide a malformed current setting.
*/
if (schema?.type === 'object') {
if (!value || typeof value !== 'object' || Array.isArray(value)) return value;
return Object.fromEntries(Object.entries(schema.properties || {})
.filter(([key]) => Object.hasOwn(value, key))
.map(([key, childSchema]) => [key, keepCurrentSchemaFields(value[key], childSchema)]));
}
if (schema?.type === 'array') {
if (!Array.isArray(value)) return value;
return value.map((item) => keepCurrentSchemaFields(item, schema.items));
}
return value;
}
function normalizeUploadedAdministrator(entry, index) {
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
@@ -33,13 +58,11 @@ function parseConfigurationFile(text) {
const configInput = Object.fromEntries(
Object.entries(parsed).filter(([key]) => key !== 'admins'),
);
const config = normalizeConfig(configInput);
const config = normalizeConfig(keepCurrentSchemaFields(configInput, rootSchema));
/*
Unknown fields remain in the normalized document so strict schema
validation reports them to the operator instead of silently losing data
from the explicitly selected file.
*/
// Filtering applies only to nonexistent keys. Values retained for current
// schema fields still have to satisfy every type, range, and format rule
// before the importer can atomically initialize the database.
assertValidConfig(config);
if (!administrators.some((admin) => admin.role === 'lockdown')) {
throw new Error('The configuration file must contain at least one lockdown administrator.');