While not perfect, foreman actually uses name, major, minor of kernel.
For server and client that will show as different kernels unless you have an unpatched client OS ( 2019 stays at the same kernel, windows 10 does not)
You can rename/alias unique OS’es discovered in foreman. In our case we added “Windows Server 2019” for that specific kernel in foreman. Windows 10 for each 6month update we label like “Windows 10 20h2” or similar.
Then in foreman they show up separately.
It’s sucky for the few times the server and desktop kernels match, but that’s like a few months every 2-3 years. Typically the windows 10 version is out before all of our server side stuff supports the latest windows server version anyways…
You can go down the road of writing your own ruby code to report facts: Custom facts overview
But if you are not already a ruby developer and want to explore Puppet in its ugly depth, I would recommend a look at external facts. This would even allow using powershell on Windows: External facts
Simply put this into the correct location of a Puppet module and it will be synced to all systems and executed and reported before every run.
As mentioned already by @Dirk - Custom facts or External Facts are the way to go.
YAML Files, TXT files, Shell Scripts, Ruby Scripts, Python Scripts - whatever really. Puppet can gather insane amounts of custom facts that you write. In our environment - we do “many” custom facts already.
PS1 script that returns the output of a WMI query for add/remove programs in the format facter wants would totally give you what you want.
One word of caution (particularly with windows) - your custom facts add to the “runtime” of fact gather portion of puppet. You really don’t want something that takes more than, say, 1 second. Too many of them and all of the sudden “fact gather” takes like 3 minutes which is annoying…
We’ve gotten to the point (again, particularly with windows) where we will setup a scheduled task for “long running” fact gather jobs - which executes maybe 1x per day, and dumps the “result” into a YAML file in the facts.d directory. That way facter/puppet can run and gather the info “quickly” without incurring the script penalty. I’d recommend that, or something similar, if your custom stuff is slow to query (LOOKING AT YOU, FREAKING WMI)