This is pretty nice. Some quick suggestions.
For your employees, consider having them use Mac or Linux desktops so 99% of malware simply won’t hit them. Downtime without leaks is still lost revenue or growth. If on Windows, use a whitelisting app to avoid issues like them opening a pdf that’s actually an executable. On all, patch as soon as you can. Backup your product info onto offline, write-once media (eg CD-R’s) on occasion.
For code, consider adding these since they cover so many problems:
Document the expections of how you think function arguments are supposed to be used in comments and/or interface checks. See Design-by-Contract for version built into the language. Reason for this is interface errors are majority of logical failures per many sources.
Validate input against expectations as malice will start with that.
Use memory-safe, concurrency-safe languages where possible. Prevents most code injections & hard-to-track errors.
Read about the common failures in networking or distributed computing. Keep them in mind for distributed interactions with some failure handling built into that.
Use libraries that are easy to use correctly with good, security record. There’s a reason Qmail was so popular among big services despite not being as full featured as some mail servers. ;)
For your application, you might also break up and/or drop privileges if it can be run without them. Getting configuration file, opening network ports, etc then dropping privileges before doing risky stuff is simpler route. Other one, for when privileges needed over time, has you split the risky stuff into its own process where the higher-privileged stuff communicates with message passing checking its input sent in simplified format and protocol. This is common in high-assurance security where we prefer to box up as much stuff as possible with critical stuff done simply, safely, and directly on a microkernel. Can do it in UNIX and stuff too.