What's wrong
Every semantic string type in Keybinding/Models carries a [GeneratedRegex] pattern and a public static Validate* method describing a strict format, but nothing calls these methods and no validation attribute is applied, so Create(...) accepts anything non-empty. Worse, the declared rules contradict behaviour the library deliberately relies on, so they can't simply be switched on.
| Type |
Declared rule |
Reality |
NoteName |
^[A-Z0-9_]+$ |
Note stores + and , as keys ("Ctrl++", "Ctrl+,", fixed in #108), and SeparatorKeyParsingTests asserts this |
CommandId |
^[a-z0-9]+(\.[a-z0-9]+)*$ ("category.action") |
Any id works: "File.Save", "myCommand", "File.Save!!" |
ProfileId |
kebab-case, at least 2 chars |
Never used: Profile.Id is a plain string |
ProfileName |
letters/digits/space/-/_ |
Never used: Profile.Name is a plain string |
ChordString, PhraseString |
letters/digits/+/,/space/-/_ |
Never referenced anywhere. Their patterns would also reject valid chords like "Ctrl+," in ChordString |
CommandName, CommandCategory, CommandDescription |
restricted character sets |
Not enforced: CommandName.Create("Save & Close") succeeds |
I checked this against the build at HEAD with a small console app:
NoteName.Create("+") -> OK "+"
NoteName.Create("a b!") -> OK "a b!"
CommandId.Create("File.Save!!") -> OK
ProfileId.Create("X") -> OK
CommandId.ValidateCommandId("File.Save") -> "Command ID must follow the format 'category.action' ..."
Why it matters
- A reader or contributor reads
ValidateNoteName/ValidateCommandId and concludes that ids and keys are restricted. They aren't, and code written on that assumption (for example, using a command id as a file name) is wrong.
- The repository's CLAUDE.md tells contributors to "use validation attributes on semantic strings". Anyone who does that for these types by wiring up the existing rules would break
+/, key bindings and every mixed-case command id that users already have in commands.json/profiles.json.
ProfileId, ProfileName, ChordString and PhraseString are public, unused API that ships in the package. The same goes for the ModifierKeys and SpecialKeys enums, which nothing in the library reads.
Suggested fix
Make the declared rules match what the library accepts, in one of two ways:
- Remove the dead rules (preferred). Delete the
GeneratedRegex/Validate* members that aren't enforced. Mark the unused public types (ProfileId, ProfileName, ChordString, PhraseString, ModifierKeys, SpecialKeys) [Obsolete] now and remove them in the next major version.
- Enforce corrected rules. If some constraint is wanted (for example, no control characters in a
NoteName), rewrite the rule so it accepts everything the library already produces and persists, including +, ,, and mixed-case or dotted command ids. Then apply it with a proper validation attribute and add tests.
Acceptance criteria
- No semantic type exposes a validation rule that
Create doesn't enforce.
- Any enforced rule accepts every key and id the existing tests and README examples use (
"+", ",", "file.save", "File.Save").
- Unused public model types are either deprecated or given a real use.
What's wrong
Every semantic string type in
Keybinding/Modelscarries a[GeneratedRegex]pattern and a public staticValidate*method describing a strict format, but nothing calls these methods and no validation attribute is applied, soCreate(...)accepts anything non-empty. Worse, the declared rules contradict behaviour the library deliberately relies on, so they can't simply be switched on.NoteName^[A-Z0-9_]+$Notestores+and,as keys ("Ctrl++", "Ctrl+,", fixed in #108), andSeparatorKeyParsingTestsasserts thisCommandId^[a-z0-9]+(\.[a-z0-9]+)*$("category.action")"File.Save","myCommand","File.Save!!"ProfileIdProfile.Idis a plainstringProfileNameProfile.Nameis a plainstringChordString,PhraseString"Ctrl+,"inChordStringCommandName,CommandCategory,CommandDescriptionCommandName.Create("Save & Close")succeedsI checked this against the build at HEAD with a small console app:
Why it matters
ValidateNoteName/ValidateCommandIdand concludes that ids and keys are restricted. They aren't, and code written on that assumption (for example, using a command id as a file name) is wrong.+/,key bindings and every mixed-case command id that users already have incommands.json/profiles.json.ProfileId,ProfileName,ChordStringandPhraseStringare public, unused API that ships in the package. The same goes for theModifierKeysandSpecialKeysenums, which nothing in the library reads.Suggested fix
Make the declared rules match what the library accepts, in one of two ways:
GeneratedRegex/Validate*members that aren't enforced. Mark the unused public types (ProfileId,ProfileName,ChordString,PhraseString,ModifierKeys,SpecialKeys)[Obsolete]now and remove them in the next major version.NoteName), rewrite the rule so it accepts everything the library already produces and persists, including+,,, and mixed-case or dotted command ids. Then apply it with a proper validation attribute and add tests.Acceptance criteria
Createdoesn't enforce."+",",","file.save","File.Save").