Skip to content

validateConditionFields ignores a condition's cross-schema targets, so branch-inactive fields go unchecked #6742

Description

@vshvets-bc

Summary

SchemaHelper.validateConditionFields — the runtime condition check reached from VCJS.conditionErrors — validates only thenFields / elseFields, the fields a condition declares itself, looked up by name in the local object:

const active = evaluate(condition) ? thenFields : elseFields;
for (const field of active) {
    if (field.required && !present(data[field.name])) {
        errors.push(`Field "${field.name}" is required.`);
    }
}

It never reads thenTargets / elseTargets — the cross-schema half of a condition, where the target lives at a fieldPath inside another sub-schema.

Why that leaves a gap

buildDocument does compile targets: buildCrossRequired emits nested properties / required, and buildCrossForbidden emits false for the other branch's targets. So targets are enforced wherever those compiled keywords apply — and unenforced everywhere they do not, with nothing in the runtime check to cover the difference.

The consequence that matters is the forbidden side: a document can carry a target belonging to the inactive branch and nothing rejects it.

Reproduce

Condition: if kind = full then sub.detail appears (target detail inside sub-schema sub).

SchemaHelper.validateConditionFields(conditions, { kind: 'partial', sub: { detail: 'smuggled' } });
// actual: []   expected: an error - the branch that reveals `detail` is not active
SchemaHelper.validateConditionFields(conditions, { kind: 'full', sub: {} });
// actual: []   expected: an error - `detail` is required on the active branch

Out of scope here, but worth recording

A condition whose trigger and target sit in two paired repeatable sub-schemas (subA[i].typesubB[i].detail) cannot be validated by this function as it stands: correlating entry i of one array with entry i of another needs the schema's arrayDependencies, and validateConditionFields(conditions, data) does not receive them. Closing that would mean changing the signature, so I have left it out of the fix rather than half-doing it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: pr open / code completeIssue has been coded with an open PR but not deployed to an environment for user acceptance testing.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions