When editing the field settings, the chosen algorithms don't persist across saves, and the keys entered aren't validated against this list. So there are really two problems here, not saving config, and validations not applying.

Steps to reproduce:
- Add an SSH Key field to an entity.
- Choose some algorithms in the field settings.
- Save field settings.
- Edit the field settings again.
- Notice that all of the boxes are unchecked, even though you previously checked some.
- Have a user save a key for an unchecked algorithm.
- Notice that it's accepted, without a form validation failure.
Remaining tasks:
- Get the field config saving properly, and
- actually validate the form field against the chosen algorithms.
| Comment | File | Size | Author |
|---|---|---|---|
| Screenshot from 2026-03-17 22-18-40.png | 4.8 KB | colan |
Comments
Comment #2
colanOkay, looks like it's saving, just not showing up on the form.
Comment #8
colanBoth bugs stemmed from related shape/typing mismatches. The settings form rendered with no boxes checked even after a save because
#default_valuewas passing the stored{algorithm: bool}mapping straight to acheckboxeselement, which expects an indexed list of selected option keys. The validator's "any algorithm allowed" symptom traced back to the hardcoded fallback list introduced in 3e0987c3, which short-circuited the per-field$constraint->algorithmdata thatSshKeyItem::getConstraints()was already passing in.Commit ca591c8 fixes the form by converting the mapping with
array_keys(array_filter($settings['algorithm']))before assigning to#default_value. Commit 49552bd fixes the validator the same way — reading$constraint->algorithmdirectly viaarray_keys(array_filter(...))and using strictin_arrayso a checkbox label like'ssh-rsa'doesn't loose-compare equal toTRUE. That second commit, however, exposed a third defect: Drupal'sConstraintFactory::createInstance()instantiates constraints by passing a single positional options array (new SshKeyConstraint(['algorithm' => [...]])), but the previous constructor's first positional parameter was$algorithm, so the entire options array landed in$this->algorithm— double-wrapped. The existing tests didn't catch this because they construct with PHP named arguments, which bypass the factory path. Commit 2716141 fixes the constructor by routing$optionsthroughparent::__construct()so Symfony's property mapping does the right thing for both calling conventions.The test suite gains two regression cases:
testValidateAlgorithmDisabledByFieldSettingsconfirms a module-supported algorithm (e.g.ssh-dss) is rejected once the field setting excludes it, andtestConstructorAcceptsOptionsArraylocks in the singly-wrapped result for both factory-style and named-arg construction.