I wanted to report back that I found what the problem was... and it was not in the keybinding code itself.
The name for my saved variables (specified in ZO_SavedVars:NewAccountWide() and ZO_SavedVars:NewCharacterIdSettings() and the manifest file) was the same as the namespace name for the addon. So, the addon namespace was being saved and reloaded by ZO_SavedVars and you cannot save functions as a saved variable - so those would get saved as value nil and reloaded that way.
That was why the global function still worked - because it was in the _G namespace instead of the addon namespace.
You can tell that you have this problem when you look at your addon saved variables file and find all sorts of addon namespace-level variables there, some of them with the value of nil and a generated comment saying that function is not a vaild type. Your addon's behaviour will be wildly unpredictable from toon to toon.
Thank you to everyone for your help.